Xyjj’s sequence

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
const int p=1e5+3;
const int maxn=1e5+10;
const int N=1e5+10;
const int M=5e3+5;
bool ok[maxn];
int prime[maxn],phi[maxn],cnt;
int a,b,n;
int u[N],v[N];
int dp[2][M][2];
//int dp[2*M][M][2];
void init()
{
    phi[1]=1;
    for(ll i=2; i<maxn; ++i)
    {
        if(!ok[i])
        {
            prime[cnt++]=i;
            phi[i]=i-1;
        }
        for(int j=0; j<cnt; ++j)
        {
            if(i*prime[j]>=maxn)break;
            ok[i*prime[j]]=1;
            if(i%prime[j]==0)
            {
                phi[i*prime[j]]=phi[i]*prime[j];//prime[j]是i的因子 prime[j]的素因子项包含在i的素因子项里
                break;
            }
            else phi[i*prime[j]]=phi[i]*(prime[j]-1);//prime[j]与i互质 phi[i*prime[j]=phi[i]*phi[prime[j]]
        }
    }
}
int modpow(int x,int n,int mod)
{
    int ans=1;
    for(; n; n/=2,x=1ll*x*x%mod)
        if(n&1)ans=1ll*ans*x%mod;
    return ans;
}
int f(int num,int mod)
{
    if(mod==1)return 0;
    if(num==1)return b%mod;
    return modpow(b,f(num-1,phi[mod])+phi[mod],mod);
}
int main()
{
    init();
    while(scanf("%d%d",&a,&b)!=EOF)
    {
        scanf("%d",&n);
        for(int i=1; i<=n; ++i)
        {
            scanf("%d",&u[i]);
            u[i]=modpow(a,f(u[i],phi[p])+phi[p],p);
        }
        for(int i=1; i<=n; ++i)
        {
            scanf("%d",&v[i]);
            v[i]=modpow(a,f(v[i],phi[p])+phi[p],p);
        }
        memset(dp,0,sizeof dp);
        u[0]=v[0]=p+1;//保证和第二项不同

        /**for(int j=1;j<=n;j++){
            for(int i=j;i<=n+j;i++){
                dp[i][j][0]=max(dp[i-1][j-1][0]+u[j]*(u[j-1]==u[j]),dp[i-1][j-1][1]+u[j]*(v[j-1]==u[j]));
                dp[i][j][1]=max(dp[i-1][j-1][1]+v[j]*(v[j-1]==v[j]),dp[i-1][j-1][0]+v[j]*(u[j-1]==v[j]));
            }
        }*/
        for(int k=0; k<=n; ++k)
        {
            int i=k&1;
            //cout<<i<<" "<<(i^1)<<'
';
            for(int j=0; j<=n; ++j)
            {
                dp[i][j][0]=0;
                dp[i][j][1]=0;
            }
            ///滚动

            ///u取第k位
            ///v取第j位
            ///如何保证无后效性??
            for(int j=0; j<=n; ++j)
            {
                if(k>0)
                {
                    dp[i][j][0]=max(dp[i][j][0],dp[i^1][j][0]+u[k]*(u[k]==u[k-1]));///u[k]的前一位可以是u[k-1]
                    dp[i][j][0]=max(dp[i][j][0],dp[i^1][j][1]+u[k]*(u[k]==v[j]));///u[k]前一位可以是v的任一位
                }
                if(j>0)
                {
                    dp[i][j][1]=max(dp[i][j][1],dp[i][j-1][0]+v[j]*(v[j]==u[k]));///v[j]的前一位可以是u的任一位
                    dp[i][j][1]=max(dp[i][j][1],dp[i][j-1][1]+v[j]*(v[j]==v[j-1]));///v[j]的前一位可以是v[j-1]
                }
            }

        }
        printf("%d
",max(dp[n&1][n][0],dp[n&1][n][1]));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/liulex/p/11366894.html