1. 程式人生 > >UPC:2219 A^X mod P(預處理空間換時間)

UPC:2219 A^X mod P(預處理空間換時間)

題意:按公式求f[x],再按公式求結果。

思路:直接搞的話f[i]可能高達10^9,n10^6,即使用快速冪也會超時。用空間換時間是一種常見的降低複雜度的辦法。對於任意一個數字X,它可以變成X=a*N+b(N為常數)。基於這個思路可以把f[n]=a*N+b,如果取N=10^5,那麼可以保證a最大為10^4,b最大為10^5。這樣A^f[n]=A^(a*N+b)=A^(a*N)*A^b=(A^N)^a*A^b。其中A^N為常數,可以線性時間求得。這樣可以線上性時間內求得(A^N)^aA^b的冪並存入陣列(0<=a<=10^4,0<=b<=10^5)。這樣求A^f[n]就是O1),求最後結果的過程可以在O

n)內完成。

#include <iostream>
#include <vector>
#include <cstring>
#include <cstdio>
using namespace std;
typedef long long LL;
const int maxn=1000005;
const int N=100000;
LL f[maxn];
LL bx[N+10];
LL ax[N+10];
int main()
{
    int T,kase=0;
    cin>>T;
    while(T--)
    {
        LL n,A,K,a,b,m,P;
        cin>>n>>A>>K>>a>>b>>m>>P;
        A%=P;
        f[1]=K;
        for(int i=2;i<=n;++i)
            f[i]=(a*f[i-1]+b)%m;
        bx[0]=1%P;
        for(int i=1;i<=N;++i)
            bx[i]=bx[i-1]*A%P;
        LL Ax=1%P;
        for(int i=1;i<=N;++i)
            Ax=(Ax*A)%P;
        ax[0]=1%P;
        for(int i=1;i<=N;++i)
            ax[i]=ax[i-1]*Ax%P;
        LL ans=0;
        for(int i=1;i<=n;++i)
        {
            int x=f[i]/N;
            int y=f[i]%N;
            LL t=ax[x]*bx[y]%P;
            ans=(ans+t)%P;
        }
        cout<<"Case #"<<++kase<<": "<<ans<<endl;
    }
    return 0;
}