题目
推导方式比较牛逼,一劳永逸
推公式最详细的博客
消去公式:
F(k1,k2,n,a,b,c)=i=0∑nik1⌊cai+b⌋k2=i=0∑nik1(⌊ca⌋i+⌊cb⌋+⌊c(amodc)i+(bmodc)⌋)k2=i=0∑nik1∑p=13jp=k2∑∏p=13jp!k!×(⌊ca⌋i)j1⌊cb⌋j2⌊c(amodc)i+(bmodc)⌋j3=∑p=13jp=k2∑∏p=13jp!k!⌊ca⌋j1⌊cb⌋j2F(k1+j1,j3,n,a%c,b%c,c)
反转公式:
令
m=⌊can+b⌋−1
F(k1,k2,n,a,b,c)=i=0∑nik1⌊cai+b⌋k2=i=0∑nik1∀p∈[1,k2],jp∈[0,m]∑p=1∏k2[jp<⌊cai+b⌋](枚举jp的最大值)=i=0∑nik1q=0∑m[q<⌊cai+b⌋][(q+1)k2−qk2](q<⌊cai+b⌋等价于i>⌊acq+c−b−1⌋)=q=0∑m[(q+1)k2−qk2](i=0∑nik−i=0∑⌊acq+c−b−1⌋ik)=[(m+1)k2−0k2]i=0∑nik−q=0∑mr=0∑k2−1(rk2)qri=0∑⌊acq+c−b−1⌋ik(将函数Sk(x)=i=0∑xik插值后得到其k+1次表达式写作Sk(x)=i=0∑k+1ak,ixi)=[(m+1)k2−0k2]i=0∑nik−r=0∑k2−1i=0∑k1+1(ik2)ak1,iq=0∑mqr⌊acq+c−b−1⌋i=[(m+1)k2−0k2]i=0∑nik−r=0∑k2−1i=0∑k1+1(ik2)ak1,iF(r,i,m,c,c−b−1,a)
这个公式真的一点都不吓人。
但是我们需要注意我们在第二行做了的这个操作。
它在前后并不是完全相等(完全恒等)的。
当
k2=0时会出现我们
∑∀p∈[1,k2],jp∈[0,m]∏p=1k2[jp<⌊cai+b⌋]为
0的情况,但实际上我们公式中这个位置应该是
1才是正确的。
但是我们经过简单的计算和验证。
我们只需要让
F(k1,k2,n,a,b,c)=(m+1)k2i=0∑nik−r=0∑k2−1i=0∑k1+1(ik2)ak1,iF(r,i,m,c,c−b−1,a)
即可解决问题。
注:实际上边界好像只用判
a=0,别的判了也没多快,记忆化是真的快。
AC Code
#include<bits/stdc++.h>
#define maxn 15
#define mod 1000000007
#define LL long long
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
using namespace std;
int inv[maxn]={1,1},fac[maxn]={1,1},invf[maxn]={1,1};
int Pow(int b,int k){
int r = 1;
for(;k;k>>=1,b=1ll*b*b%mod)
if(k&1)
r=1ll*r*b%mod;
return r;
}
int C(int n,int m){
static int c[maxn][maxn]={},f=0;
if(!f){
c[0][0]=f=1;
rep(i,1,maxn-1) rep(j,c[i][0]=1,i) c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
}
return c[n][m];
}
int a[maxn][maxn];
int S(int n,int m){
n %= mod;
LL r = 0 , pw = 1;
rep(j,0,m+1) r = (r + 1ll * a[m][j] * pw) , pw = 1ll * pw * n % mod;
return (r % mod + mod) % mod;
}
int f[maxn][maxn][50];
int F(int k1,int k2,int n,int a,int b,int c,int dep=0){
if(~f[k1][k2][dep]) return f[k1][k2][dep];
if(a == 0) return f[k1][k2][dep] = (1ll * Pow(b/c,k2) * S(n,k1) % mod + mod) % mod;
if(a>=c||b>=c){
int r = 0 , A = a % c , B = b % c;a /= c , b /= c;
int pwa[maxn]={},pwb[maxn]={};
rep(j,pwa[0]=pwb[0]=1,k2)
pwa[j]=1ll*pwa[j-1]*a%mod,
pwb[j]=1ll*pwb[j-1]*b%mod;
rep(j1,0,k2) rep(j2,0,k2-j1){ int j3 = k2 - j1 - j2;
r = (r + 1ll * pwa[j1] * pwb[j2] % mod * invf[j1] % mod * invf[j2] % mod * invf[j3] % mod * F(k1+j1,j3,n,A,B,c,dep+1)) % mod;
}
return f[k1][k2][dep] = ((1ll * r * fac[k2] % mod)+mod)%mod;
}
int m = (1ll * a * n + b) / c - 1 , r = 1ll * Pow(m+1,k2) * S(n,k1) % mod;
rep(i,0,k2-1) rep(j,0,k1+1) r = (r - 1ll * C(k2 , i) * ::a[k1][j] % mod * F(i,j,m,c,c-b-1,a,dep+1)) % mod;
return f[k1][k2][dep]=(r+mod)%mod;
}
int main(){
rep(i,2,maxn-1)
inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod,
fac[i]=1ll*fac[i-1]*i%mod,
invf[i]=1ll*invf[i-1]*inv[i]%mod;
a[0][1] = a[0][0] = 1;
rep(i,1,maxn-2){
rep(j,0,i+1) a[i][j] = C(i+1,j);
rep(j,0,i-1) rep(k,0,j+1)
a[i][k] = (a[i][k] - 1ll * C(i+1,j) * a[j][k]) % mod;
rep(j,0,i+1) a[i][j] = 1ll * a[i][j] * inv[i+1] % mod;
}
int T,n,a,b,c,k1,k2;
for(scanf("%d",&T);T--;){
scanf("%d%d%d%d%d%d",&n,&a,&b,&c,&k1,&k2);
memset(f,-1,sizeof f);
printf("%d\n",(F(k1,k2,n,a,b,c)+mod)%mod);
}
}