ZOJ Power of Fibonacci(二次剩余+逆元) HDU 6755 Fibonacci Sum(卡常 未AC)

ZOJ 题目链接   Power of Fibonacci

HDU 6755 Fibonacci Sum

ZOJ:

HDU题意

给定n 和ck,其中0<=n,c<=1e18,1<=k<=1e5,求S=(F_{0}^k+F_{c}^k+F_{2c}^{k}+......+F_{nc}^k)mod 1e9+9

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应该是 t=(a^{k-r}b^{r})^c

但是这题卡常,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;
}

猜你喜欢

转载自blog.csdn.net/qq_41286356/article/details/107517138