hdu 6333-数論+莫隊
タイトルリンク:ここをクリック
問題解決の考え方:
またS(n,m)=c(n,0)+c(n,1)+c(n,2)+…+c(n,m)
ではS(n,m)=S(n,m−1)+c(n,m)
またc(n+1,1)+c(n+1,2)+...+c(n+1,m) = S(n,m)+c(n,1)+c(n,2)+c(n,3) +...c(n,m−1)->c(n+1,k)=c(n,k)+c(n,k−1)から得られる
両側+1得:c(n+1,0)+c(n+1,1)+c(n+1,2)+...+c(n+1,m) = S(n,m)+c(n,0)+c(n,1)+c(n,2)+c(n,3) +...c(n,m-1)
S(n+1,m) = 2*S(n,m) - c(n,m)
S(n,m)を知れば,S(n+1,m),S(n−1,m),S(n,m+1),S(n,m+1),S(n,m−1)をO(1)で知ることができる.
mをlと見なし,nをrと見なし,ブロックを分けて莫隊を走る.時間の複雑さはO(n*ルートn)です.
問題解決の考え方:
またS(n,m)=c(n,0)+c(n,1)+c(n,2)+…+c(n,m)
ではS(n,m)=S(n,m−1)+c(n,m)
またc(n+1,1)+c(n+1,2)+...+c(n+1,m) = S(n,m)+c(n,1)+c(n,2)+c(n,3) +...c(n,m−1)->c(n+1,k)=c(n,k)+c(n,k−1)から得られる
両側+1得:c(n+1,0)+c(n+1,1)+c(n+1,2)+...+c(n+1,m) = S(n,m)+c(n,0)+c(n,1)+c(n,2)+c(n,3) +...c(n,m-1)
S(n+1,m) = 2*S(n,m) - c(n,m)
S(n,m)を知れば,S(n+1,m),S(n−1,m),S(n,m+1),S(n,m+1),S(n,m−1)をO(1)で知ることができる.
mをlと見なし,nをrと見なし,ブロックを分けて莫隊を走る.時間の複雑さはO(n*ルートn)です.
#include
using namespace std;
const int mx = 1e5 + 10;
const int mod = 1e9 + 7;
typedef long long ll;
ll inv[mx],f[mx],ans[mx];
int n,m,block;
struct node
{
int l,r;
int pos;
bool operator < (node A)const
{
if(l/block!=A.l/block) return l < A.l;
return r < A.r;
}
}s[mx];
void init(){
inv[0] = inv[1] = 1;
for(int i = 2; i < mx; i++){
inv[i] = (ll)(mod-mod/i)*inv[mod%i]%mod;
}
f[0] = 1;
for(int i = 1; i < mx; i++){
f[i] = f[i-1]*i%mod;
}
for(int i = 1; i < mx; i++){
inv[i] = inv[i]*inv[i-1]%mod;
}
for(int i=mx-2;i>=1;i--) inv[i] = inv[i+1]*(i+1)%mod;
}
int main()
{
int t,ma = 0;
scanf("%d",&t);
init();
for(int i=1;i<=t;i++){
scanf("%d%d",&s[i].r,&s[i].l);
ma = max(ma,s[i].r);
s[i].pos = i;
}
block = sqrt(ma);
sort(s+1,s+1+t);
int L = 0,R = 0;
ll val = 1;
for(int i=1;i<=t;i++){
while(Rs[i].r) R--,val = (val+f[R]*inv[L]%mod*inv[R-L]%mod)%mod*inv[2]%mod;
while(Ls[i].l) val = (val-f[R]*inv[L]%mod*inv[R-L]%mod+mod)%mod,L--;
ans[s[i].pos] = val;
}
for(int i=1;i<=t;i++) printf("%lld
",ans[i]);
return 0;
}