ZOJ:
HDU题意
给定 和和,其中,,求
ZOJ 分析做法参考来自:博客
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 100005;
const ll mod = 1000000009;
ll fac[N],A[N],B[N],inv[N];
void Init()
{
fac[0] = 1,A[0] = B[0] = 1;
for(int i=1; i<N; i++) fac[i] = fac[i-1] * i % mod;
for(int i=1; i<N; i++){
A[i] = A[i-1] * 691504013 % mod;
B[i] = B[i-1] * 308495997 % mod;
}
inv[0]=1,inv[1]=1;
for(int i=2;i<N;i++)
inv[i]=ll(mod-mod/i)*inv[mod%i]%mod;
for(int i=1;i<N;i++)
inv[i]=inv[i-1]*inv[i]%mod;
}
ll powmod(ll a,ll b,ll mod)
{
ll res=1;a%=mod;
for(;b;b>>=1){
if(b&1) res=res*a%mod;
a=a*a%mod;
}
return res;
}
ll getC(ll n,ll m)
{
if(m>n||n<0||m<0)return 0;
if(m==0||m==n) return 1;
return (fac[n]*inv[m]%mod*inv[n-m])%mod;
}
ll Solve(ll n,ll k)
{
ll ans = 0;
for(int r=0; r<=k; r++){
ll t = A[k-r] * B[r] % mod;
ll c=getC(k,r);
ll tmp = t * (powmod(t,n,mod) - 1) % mod * powmod(t-1,mod-2,mod) % mod;
if(t == 1) tmp = n % mod;
tmp = tmp * c % mod;
if(r & 1) ans -= tmp;
else ans += tmp;
ans %= mod;
}
ll m = powmod(383008016,mod-2,mod);
ans = ans * powmod(m,k,mod) % mod;
ans = (ans % mod + mod) % mod;
return ans;
}
int main()
{
int T;
ll n,k;
Init();
scanf("%d",&T);
while(T--)
{
cin>>n>>k;
cout<<Solve(n,k)<<endl;
}
return 0;
}
对于HDU 的题 也是类似的分析:
最后不同的地方是
t应该是
但是这题卡常,for循环里面只允许用一次快速幂,我赛时ac的代码 赛后交 超时了。。。。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 100005;
const ll mod = 1000000009;
ll fac[N],A[N],B[N],inv[N];
void Init()
{
fac[0] = 1,A[0] = B[0] = 1;
for(int i=1; i<N; i++) fac[i] = fac[i-1] * i % mod;
for(int i=1; i<N; i++){
A[i] = A[i-1] * 691504013 % mod;
B[i] = B[i-1] * 308495997 % mod;
}
inv[0]=1,inv[1]=1;
for(int i=2;i<N;i++)
inv[i]=ll(mod-mod/i)*inv[mod%i]%mod;
for(int i=1;i<N;i++)
inv[i]=inv[i-1]*inv[i]%mod;
}
ll powmod(ll a,ll b,ll mod)
{
ll res=1;a%=mod;
for(;b;b>>=1){
if(b&1) res=res*a%mod;
a=a*a%mod;
}
return res;
}
ll getC(ll n,ll m)
{
if(m>n||n<0||m<0)return 0;
if(m==0||m==n) return 1;
return (fac[n]*inv[m]%mod*inv[n-m])%mod;
}
ll Solve(ll n,ll C,ll k)
{
ll ans = 0;
ll t1=powmod(A[1],C,mod),t2=powmod(B[1],C,mod);
ll invv=powmod(t1,mod-2,mod);
ll T1=powmod(t1,k,mod),T2=1;
for(int r=0,flag=1; r<=k; r++,flag=-flag){
// ll t = powmod(A[k-r] * B[r] % mod,C,mod);
ll t=T1*T2%mod;//优化1
ll tmp,c=getC(k,r);
if(t == 1) {
tmp = n % mod;
tmp = tmp * c % mod;
ans=(ans+flag*tmp+mod)%mod;
}
else{
tmp = t * (powmod(t,n,mod) - 1) % mod * powmod(t-1,mod-2,mod) % mod;
tmp = tmp * c % mod;
ans=(ans+flag*tmp+mod)%mod;
}
T1=T1*invv%mod,T2=T2*t2%mod;
}
ll m = powmod(383008016,mod-2,mod);
ans = ans * powmod(m,k,mod) % mod;
ans = (ans % mod + mod) % mod;
return ans;
}
inline ll read()
{
ll x=0,w=1; char c=getchar();
while(c<'0'||c>'9') {if(c=='-') w=-1; c=getchar();}
while(c<='9'&&c>='0') {x=(x<<1)+(x<<3)+c-'0'; c=getchar();}
return w==1?x:-x;
}
int main()
{
Init();
int T=read();
while(T--)
{
ll n=read(),C=read(),k=read();
printf("%lld\n",Solve(n,C,k));
}
return 0;
}