这道题没写过类似的感觉确实不好想,考点在与二项式求和优化等式。特别是优化等式这里,是真的坑。
废话不多说,上推到过程:
因为:
可以有:
所以有二项式展开:
很明显竖起来是等比,所以这样就可以把复杂度变成klogn了;
然后可以得出公式S结果公式为:
由于需要mod1e9+9,所以可以由费马小定理可知变形为:
qi的值和阶乘的值都可以预处理,但是你会发现如果直接带这个公式写出来就T了。这就是真的变态卡快速幂。。。。。。。。。
这是我超时的代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll P = 1e9+9;
const ll maxn = 1e5+5;
ll a[maxn],b[maxn],jie[maxn];
void pre(){
jie[0]=1;
//预处理阶乘
for(ll i=1;i<maxn;i++)jie[i]=jie[i-1]*i%P;
//预处理a,b
a[0]=1;b[0]=1;
for(ll i=1;i<maxn;i++){
a[i]=a[i-1]*691504013%P;//a的%P的逆元
b[i]=b[i-1]*308495997%P;//b的%p的逆元
}
}
ll QP(ll x,ll n){
ll res=1;
while(n){
if(n&1){
res=res*x%P;
}
x=x*x%P;
n>>=1;
}
return res;
}
ll T;
ll N,C,K;
int main(){
scanf("%lld",&T);
pre();
ll ans=0;
ll x=QP(383008016,P-2);//利用费马小定理求1/sqrt(5)%P的值
while(T--){
ans=0;
scanf("%lld %lld %lld",&N,&C,&K);
ll t=QP(a[K],C)%P;
for(ll i=0;i<=K;i++){
ll fenzi=jie[K];
ll fenmu=jie[i]*jie[K-i]%P;
ll res=fenzi*QP(fenmu,P-2)%P;
ll temp=t*(QP(t,N)-1)%P*QP(t-1,P-2)%P;//这里有个十分奇葩的地方,我开头把他分开写居然wa了而不是T了。。。。。。。
if(t==1){//分母没有意义,求和可知为N
temp=N%P;
}
temp=temp*res%P;
if(i&1) ans-=temp;//如果为负数
else ans+=temp;//如果为正数
ans%=P;
}
ans=QP(x,K)*ans%P;
ans=(ans%P+P)%P;//防止负数
printf("%lld\n",ans);
}
return 0;
}
然后就很懵逼了,这怎么搞的?????崩溃。。。。。。。
参考大佬的代码优化因为后一个q的值就是前一个q的值乘上A(-C)*B^C;
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+9;
const ll MAXN=1e5;
ll factor[MAXN+10];
ll invFactor[MAXN+10];
ll invn[MAXN+10];
const ll A=691504013;
const ll invA=691504012;
const ll B=308495997;
const ll D=276601605;
ll QP(ll x, ll n)
{
ll res=1;
while(n)
{
if (n&1) res=res*x%mod;
x=x*x%mod;
n>>=1;
}
return res;
}
ll Mod(ll a, ll b)
{
a+=b;
if (a>=mod)
a-=mod;
return a;
}
void pre()
{
factor[0]=invFactor[0]=invn[0]=factor[1]=invFactor[1]=invn[1]=1;
for(int i=2; i<=MAXN; i++)
{
factor[i]=factor[i-1]*i%mod;
invn[i]=(ll) (mod-mod/i)*invn[mod%i]%mod;
invFactor[i]=invFactor[i-1]*invn[i]%mod;
}
}
ll getC(ll m, ll n)//求C(n,m)
{
if (n<0 || m<0 || m>n)
return 0;
ll ans=factor[n];
ans=(ll) ans*invFactor[m]%mod;
ans=(ll) ans*invFactor[n-m]%mod;
return ans;
}
int main()
{
pre();
int T;
scanf("%d", &T);
while(T--)
{
ll n, c, k;
scanf("%lld%lld%lld", &n, &c, &k);
ll ans=0;
ll a1=QP(QP(A, k), c%(mod-1));
ll q=QP((ll) invA*B%mod, c%(mod-1));
ll n1=n%mod;
ll n2=n%(mod-1);
ll a1power=QP(a1, n2);
ll qpower=QP(q, n2);
for(int i=0; i<=k; i++)
{
ll sum=getC(i, k);
if (i&1)
{
sum=mod-sum;
}
if (a1==1)
{
ans=(ans+sum*n1%mod)%mod;
}
else
{
sum=sum*(a1*(a1power-1+mod)%mod)%mod;
sum=sum*QP(a1-1, mod-2)%mod;
ans=Mod(ans, sum);
}
a1=a1*q%mod;
a1power=a1power*qpower%mod;
}
printf("%lld\n",ans*QP(D,k)%mod);
}
}
实属想不到。。。。。。。