n n n忘记取模调了半个小时祭。
f
i
b
fib
fib是有通项公式的,然后式子写出来就是这样:
设
x
=
1
+
5
2
,
y
=
1
−
5
2
,
z
=
1
5
x=\frac{1+\sqrt{5}}{2},y=\frac{1-\sqrt{5}}{2},z=\frac{1}{\sqrt{5}}
x=21+5,y=21−5,z=51
a
n
s
=
∑
i
=
1
n
z
k
×
(
x
i
−
y
i
)
k
ans=\sum_{i=1}^n z^k\times (x^i-y^i)^k
ans=i=1∑nzk×(xi−yi)k
进一步化简,用二项式定理展开,把后面无关的往前提,发现后面其实是一个等比数列求和,不断化简最终式子就变成:
设
a
=
x
i
×
y
k
−
i
a=x^i\times y^{k-i}
a=xi×yk−i
a
n
s
=
z
k
×
∑
i
=
0
k
(
−
1
)
k
−
i
×
C
k
i
×
a
−
a
n
+
1
1
−
a
ans=z^k\times \sum_{i=0}^k(-1)^{k-i}\times C_{k}^i\times \frac{a-a^{n+1}}{1-a}
ans=zk×i=0∑k(−1)k−i×Cki×1−aa−an+1
注意要求一下 5 5 5的二次剩余,求解代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define LL long long
using namespace std;
const int mod=1e9+9;
int n=5,w;
inline int qpow(int x,int k){
int ret=1;
while(k){
if(k&1) ret=1LL*ret*x%mod;
x=1LL*x*x%mod; k>>=1;
} return ret;
}
struct F{
int x,y;
F(){}
F(const int &xx,const int &yy){x=xx,y=yy;}
F operator *(const F &b) const{
return F((1LL*x*b.x%mod+1LL*y*b.y%mod*w%mod)%mod,(1LL*y*b.x%mod+1LL*x*b.y%mod)%mod);
}
};
inline F qpow(F x,int k){
F ret(1,0);
while(k){
if(k&1) ret=ret*x;
x=x*x; k>>=1;
} return ret;
}
int main(){
while(1){
int a=1LL*rand()*rand()%mod;
w=(1LL*a*a%mod-n+mod)%mod;
if(qpow(w,(mod-1)>>1)==mod-1){
F ans=qpow(F(a,1),(mod+1)>>1);
cout<<ans.x<<endl; break;
}
}
}
最后 A C AC AC代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define LL long long
#define maxn 100005
using namespace std;
const int sq5=616991993,mod=1e9+9;
int t,k,fac[maxn],inv[maxn],a[maxn],b[maxn];
LL n;
inline LL qpow(int x,LL k){
LL ret=1;
while(k){
if(k&1LL) ret=1LL*ret*x%mod;
x=1LL*x*x%mod; k>>=1;
} return ret;
}
inline LL C(int n,int m){ return 1LL*fac[n]*inv[m]%mod*inv[n-m]%mod;}
int main(){
scanf("%d",&t); fac[0]=1;
for(int i=1;i<=100000;i++) fac[i]=1LL*fac[i-1]*i%mod;
inv[100000]=qpow(fac[100000],mod-2);
for(int i=100000;i;i--) inv[i-1]=1LL*inv[i]*i%mod;
a[0]=b[0]=1;
for(int i=1;i<=100000;i++) a[i]=1LL*a[i-1]*(1+sq5)%mod*inv[2]%mod,b[i]=1LL*b[i-1]*(1-sq5+mod)%mod*inv[2]%mod;
while(t--){
scanf("%lld%d",&n,&k);
LL ans=0;
for(int i=0;i<=k;i++){
LL tmp=1LL*a[i]*b[k-i]%mod,res=0;
if(tmp==1) res=C(k,i)*(n%mod)%mod;//!!!
else res=C(k,i)*((qpow(tmp,(n+1)%(mod-1))-tmp+mod)%mod)%mod*qpow(tmp-1,mod-2)%mod;
if(!((k-i)&1)) (ans+=res)%=mod;
else (ans+=mod-res)%=mod;
}
ans=ans*qpow(qpow(sq5,mod-2),k)%mod;
printf("%lld\n",ans);
}
return 0;
}