2019 ACM Nanchang National Invitational Xyjj's sequence (Euler descending + DP)

Topic Source: https://nanti.jisuanke.com/t/40255

Euler first understand the meaning of the title descending out of the count value, then dp is calculated.

Note dp array of topics memory card, it is necessary to calculate the starting rolling in the form of an array, or will RE.

Note that you can use MOD is exponential, so the outermost layer of computing time or starting normal power quickly.

After DP, large, since a, b relative order of the sequence will not change, so it provided a dp [2] [i] [j], dp [0/1] [i] [j] represents a array before the i-th, j-th front of the array b MAX, 0 or 1 indicates the end or ending in the array b as a array to transfer to form n ^ 2.

Then scroll instead of an array to calculate, just hold on a value of ok.

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<vector>
#include<algorithm>
#include<map>
#include<queue>
#define MAX_len 50100*4
using namespace std;
typedef long long ll;
const ll p=1e5+3;
const ll MAX=1e5+10;
ll aa[5010],bb[5010];
ll phi[MAX],dp[2][2][5010];
ll MOD(ll n,ll mod)
{
    return n<mod?n:(n%mod+mod);
}
void Euler()
{
     phi[1]=1;  
     for(ll i=2;i<MAX;i++)  
       phi[i]=i;  
     for(ll i=2;i<MAX;i++)  
        if(phi[i]==i)
           for(ll j=i;j<MAX;j+=i)  
              phi[j]=phi[j]/i*(i-1);
}
ll quickpow(ll a,ll n,ll mod)
{
    ll res=1;
    while(n)
    {
        if(n&1)
        {
             res=MOD(a*res,mod);
        }
        n>>=1;
         a=MOD(a*a,mod);
    }
    return res;
}
ll fastpow(ll a,ll n,ll mod)
{
	ll res=1;
	while(n)
	{
		if(n&1)
		res=(res*a)%mod;
	n/=2;
		a=(a*a)%mod;
	}
	return res;
} 
ll solve(ll a,ll b,ll mod)
{
    if(b==1||mod==1)
    return MOD(a,mod);
    {
    	return quickpow(a,solve(a,b-1,phi[mod]),mod);
	}
}
int main()
{
	Euler();
	int a,b,i,j,n;
	scanf("%d %d",&a,&b);
	scanf("%d",&n);
	for(i=1;i<=n;i++)
	{
		scanf("%d",&aa[i]);
		if(a==1)
		{
			aa[i]=1;
			continue;
		}
		else
		{
			aa[i]=fastpow(a,solve(b,aa[i],phi[p]),p);
		}
	}
	for(i=1;i<=n;i++)
	{
		scanf("%d",&bb[i]);
		if(a==1)
		{
			bb[i]=1;
			continue;
		}
		else
		{
			bb[i]=fastpow(a,solve(b,bb[i],phi[p]),p);
		}
	}
//	for(i=1;i<=n;i++)
//	{
//		printf("%lld %lld\n",aa[i],bb[i]);
//	}
	for(i=1;i<=n;i++)//a数组用1表示结尾,b数组用0表示结尾。之后分6种情况去判断就行了
	{
        for(j=1;j<=n;j++)
		{
            dp[0][i&1][j]=dp[1][i&1][j]=0;
            dp[0][i&1][j]=dp[1][i&1][j]=0;
            if(bb[j]==bb[j-1])
			{
                dp[0][i&1][j]=max(dp[0][i&1][j],dp[0][i&1][(j-1)]+bb[j]);
            }
            else
			{
                dp[0][i&1][j]=max(dp[0][i&1][j],dp[0][i&1][(j-1)]);
            }
            if(aa[i]==aa[i-1])
			{
                dp[1][i&1][j]=max(dp[1][i&1][j],dp[1][(i-1)&1][j]+aa[i]);
            }
            else
			{
                dp[1][i&1][j]=max(dp[1][i&1][j],dp[1][(i-1)&1][j]);
            }
            if(bb[j]==aa[i])
			{
                dp[0][i&1][j]=max(dp[0][i&1][j],dp[1][i&1][(j-1)]+bb[j]);
                dp[1][i&1][j]=max(dp[1][i&1][j],dp[0][(i-1)&1][j]+aa[i]);
            }
            else
			{
                dp[0][i&1][j]=max(dp[0][i&1][j],dp[1][i&1][(j-1)]);
                dp[1][i&1][j]=max(dp[1][i&1][j],dp[0][(i-1)&1][j]);
            }
        }
    }
    printf("%lld",max(dp[0][n&1][n],dp[1][n&1][n]));
	return 0;
}

 

Published 56 original articles · won praise 17 · views 2320

Guess you like

Origin blog.csdn.net/weixin_43958964/article/details/102303801