WXH太神了!T1还是找规律找出来的。。。T_T
Problem C.多项式
求 ∑mi=1xi≤S,∀1≤i≤nxi≤T,∀xi≥0 的解数
T,n,m≤109,n×T≤S,m−n≤1000
题解:枚举前
n
项的和,即:
这是一个 m−n 次多项式,即求:
ans=∑m−nj=0aj∑Tx1=1∑Tx2=1...∑Txn=1(∑xi)j
令 g(n,j)=∑Tx1=1∑Tx2=1...∑Txn=1(∑xi)j ,考虑倍增转移这个东西,即:
g(2n,j)=∑jk=0g(n,k)g(n,j−k)(jk)
又 g(1,j)=∑Ti=1ik
所以这题就直接暴力插值出 g(1,j) ,然后倍增暴力卷积,然后暴力算多项式系数,复杂度 O((m−n)2logn)
其实这题拿个伯努利数快速算 g(1,j) ,然后分治FFT+倍增FFT可以做到 log 的复杂度。。。但是鬼才写那玩意儿
#include<bits/stdc++.h>
#define mod 1000109107
#define maxn 1010
using namespace std;
typedef long long ll;
ll S,T,n,m;
int a[maxn],M,h[maxn],pri[maxn],psz,c[maxn],f[maxn],vis[maxn];
int g[maxn],p[maxn],C[maxn][maxn],pre[maxn],suf[maxn],fac[maxn],inv[maxn];
int qpow(int a,int b){
int ans=1;
for(;b;b>>=1,a=1ll*a*a%mod)
if(b&1)ans=1ll*ans*a%mod;
return ans;
}
int cal(int x){
if(x==0)return T;
f[1]=1;
int ans=0,D=x+2;
for(int i=2;i<=D;++i)
if(!vis[i])f[i]=qpow(i,x);
else f[i]=1ll*f[i/c[i]]*f[c[i]]%mod;
if(T<=D){
for(int i=1;i<=T;++i)
ans=(ans+f[i])%mod;
return ans;
}
pre[0]=suf[D+1]=1;
for(int i=1;i<=D;++i)pre[i]=1ll*pre[i-1]*(T-i+mod)%mod;
for(int i=D;i>=1;--i)suf[i]=1ll*suf[i+1]*(T-i+mod)%mod;
for(int i=1,sum=0;i<=D;++i){
sum=(sum+f[i])%mod;
ans=(ans+1ll*inv[i-1]*inv[D-i]%mod*(D-i&1?mod-1:1)%mod*pre[i-1]%mod*suf[i+1]%mod*sum)%mod;
}
return ans;
}
void mul(int g[],int h[],int ans[]){
for(int i=0;i<=M;++i)p[i]=0;
for(int i=0;i<=M;++i)if(g[i])
for(int j=0;i+j<=M;++j)if(h[j])
p[i+j]=(p[i+j]+1ll*g[i]*h[j]%mod*C[i+j][i])%mod;
for(int i=0;i<=M;++i)ans[i]=p[i];
}
void sol(ll n){
if(n==0){
g[0]=1;
return ;
}
if(n==1){
for(int i=0;i<=M;++i)g[i]=h[i];
return ;
}
sol(n/2);
mul(g,g,g);
if(n&1)mul(g,h,g);
}
int main(){
cin>>S>>T>>n>>m,M=m-n;
a[0]=1,S%=mod,T%=mod;
for(int i=2;i<=M+1;++i){
if(!vis[i])pri[++psz]=i;
for(int j=1,A;j<=psz&&i*pri[j]<=M+1;++j){
vis[A=i*pri[j]]=1,c[A]=pri[j];
if(i%pri[j]==0)break;
}
}
fac[0]=inv[0]=1;
for(int i=1;i<=M+1;++i)fac[i]=1ll*fac[i-1]*i%mod;
inv[M+1]=qpow(fac[M+1],mod-2);
for(int i=M;i>=1;--i)inv[i]=1ll*inv[i+1]*(i+1)%mod;
for(int i=1;i<=M;++i)
for(int j=i-1;j>=0;--j)
a[j+1]=(a[j+1]+mod-a[j])%mod,
a[j]=1ll*a[j]*(S-i+1+mod)%mod;
// for(int i=0;i<=M;++i)printf("{%d}",a[i]);puts("");
for(int i=0;i<=M;++i)h[i]=cal(i);//,printf("{%d}",h[i]);
for(int i=0;i<=M+1;++i)
for(int j=*C[i]=1;j<=i;++j)
C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
sol(n);
int ans=0;
for(int i=0;i<=M;++i)
ans=(ans+1ll*g[i]*a[i])%mod;
printf("%d\n",1ll*ans*inv[M]%mod);
}