标签:sqrt def ons 一个 nod str 相关 turn problem
? 莫队算法。可以有这样定义
\[
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
(待补。。。)
标签:sqrt def ons 一个 nod str 相关 turn problem
原文地址:https://www.cnblogs.com/Chirsilver/p/11254249.html