mo题
Posted chirsilver
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mo题相关的知识,希望对你有一定的参考价值。
https://vjudge.net/problem/HDU-6333
官方题解:
? 莫队算法。可以有这样定义
\[
S(n,m)=C_n^0+C_n^1+C_n^2+\cdots+C_n^m
\]
然后很明显就能知道这样得关系
\[
S(n,m)=S(n,m-1)+C_n^m
\]
\[ S(n,m)=2*S(n-1,m)-C_n-1^m \]
这样知道 S(n, m) 可以有O(1)得代价去得到S(n-1, m) S(n+1, m) S(n,m-1) S(n, m+1)
剩下的就是一个莫队板子了。
const ll maxn=1e5+7;
const ll mod=1e9+7;
struct node
ll n, m, id;
Q[maxn];
ll ans[maxn];
ll fac[maxn]; //阶乘
ll ni[maxn]; //逆元
ll N,M,Ans,ni2,sz; //sz表示根号MAX
ll qm(ll a, ll b)
ll res=1;
while(b)
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
return res%mod;
bool cmp(node a, node b)
if(a.n/sz==b.n/sz) return a.m<b.m;
return a.n/sz<b.n/sz;
void init()
fac[0]=1;
ni2=qm(2, mod-2);
for(int i=1; i<maxn; i++)
fac[i]=fac[i-1]*i%mod; //计算阶乘
ni[maxn-1]=qm(fac[maxn-1], mod-2);
for(int i=maxn-2; i>=0; i--)
ni[i]=ni[i+1]*(i+1)%mod; //计算逆元
ll C(ll n, ll m)
return fac[n]*ni[n-m]%mod*ni[m]%mod;
int main()
//freopen("in.txt", "r", stdin);
ll t;
cin>>t;
sz=sqrt(maxn);
init();
for(int i=0; i<t; i++)
cin>>Q[i].n>>Q[i].m;
Q[i].id=i;
sort(Q,Q+t,cmp);
N=1;M=1;Ans=2;
for(int i=0;i<t;i++)
while(N<Q[i].n)
++N;
Ans=(Ans*2%mod+mod-C(N-1, M))%mod;
while(N>Q[i].n)
Ans=(Ans+C(N-1, M))%mod*ni2%mod;
N--;
while(M<Q[i].m)
++M;
Ans=(Ans+C(N, M))%mod;
while(M>Q[i].m)
Ans=(Ans+mod-C(N, M))%mod;
M--;
ans[Q[i].id]=Ans;
for(int i=0;i<t;i++)
cout<<ans[i]<<endl;
return 0;
还有相关练习题。。
https://vjudge.net/problem/CodeForces-617E
https://vjudge.net/problem/CodeForces-86D
https://vjudge.net/problem/SPOJ-DQUERY
https://vjudge.net/problem/HYSBZ-2038
(待补。。。)
以上是关于mo题的主要内容,如果未能解决你的问题,请参考以下文章
Leetcode练习(Python):数学类:第29题:两数相除:给定两个整数,被除数 dividend 和除数 divisor。将两数相除,要求不使用乘法除法和 mo(