The 2019 ICPC China Nanchang National Invitational and International Silk-Road Programming Contest C. Xyjj’s sequence(动态规划+欧拉降幂)

题目链接:https://nanti.jisuanke.com/t/40255

中文题面:

解题思路:先用欧拉降幂求出A,B两个序列,定义dp【0】【i】【j】为取A的前i个元素,B的前j个元素,且C的最后一个元素为B【j】,同理dp【1】【i】【j】为取A的前i个元素,B的前j个元素,且C的最后一个元素为A【i】,那么就很容易得到状态转移方程。那么最后答案即为max(dp【0】【n】【n】,dp【1】【n】【n】)。还有值得注意的是:该题需要使用滚动数组,不然会超内存。

在此贴两个关于欧拉降幂的链接吧:https://blog.csdn.net/qq_37632935/article/details/81264965

https://blog.csdn.net/u013534123/article/details/78912721

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=100003;
const int maxn=5003;
int v1[maxn],v2[maxn];
ll a1[maxn],b1[maxn];
ll dp[2][3][maxn];
ll Mod(ll n,ll m){
	return n<m?n:(n%m+m);
}
ll ph(ll n){
	ll ans=n;
	ll res=n;
	for(int i=2;i*i<=res;i++){
		if(n%i==0){
			ans=ans/i*(i-1);
			while(n%i==0){
				n/=i;
			}
		}
	}
	if(n>1)ans=ans/n*(n-1);
	return ans;
}
ll qpow(ll n,ll m,ll mo){
//	cout<<"YES\n";
	ll ans=1;
	while(m){
		if(m&1)ans=ans*n%mo;
		m/=2;
		n=n*n%mo;
	}
	return ans;
}
ll solve(int num,ll mo,ll tt){
	if(num==1||mo==1)return Mod(tt,mo);
	return qpow(tt,solve(num-1,ph(mo),tt)+ph(mo),mo);
}
int main(){
	ll a,b;
	scanf("%lld%lld",&a,&b);
	int n;
	scanf("%d",&n);
	for(int i=0;i<n;i++){
		scanf("%d",&v1[i]);
	}
	for(int i=0;i<n;i++){
		scanf("%d",&v2[i]);
	}
	for(int i=0;i<n;i++){
		a1[i+1]=qpow(a,solve(v1[i],mod-1,b)+mod-1,mod);
	}
	for(int i=0;i<n;i++){
		b1[i+1]=qpow(a,solve(v2[i],mod-1,b)+mod-1,mod);
	}
	for(int i=1;i<=n;i++){//1
		for(int j=1;j<=n;j++){//0
			dp[0][i&1][j]=dp[1][i&1][j]=0;
			if(b1[j]==a1[i]){
				dp[0][i&1][j]=max(dp[0][i&1][j],dp[1][i&1][(j-1)]+b1[j]);
				dp[1][i&1][j]=max(dp[1][i&1][j],dp[0][(i-1)&1][j]+a1[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]);
			}
			if(b1[j]==b1[j-1]){
				dp[0][i&1][j]=max(dp[0][i&1][j],dp[0][i&1][(j-1)]+b1[j]);
			}
			else{
				dp[0][i&1][j]=max(dp[0][i&1][j],dp[0][i&1][(j-1)]);
			}
			if(a1[i]==a1[i-1]){
				dp[1][i&1][j]=max(dp[1][i&1][j],dp[1][(i-1)&1][j]+a1[i]);
			}
			else{
				dp[1][i&1][j]=max(dp[1][i&1][j],dp[1][(i-1)&1][j]);
			}
	//		cout<<i<<" "<<j<<" "<<dp[0][i&1][j]<<" "<<dp[1][i&1][j]<<endl;
		}
	}
	cout<<max(dp[0][n&1][n],dp[1][n&1][n])<<endl;
	return 0;
}

  

原文地址:https://www.cnblogs.com/Zhi-71/p/11618661.html

时间: 2024-07-31 11:35:08

The 2019 ICPC China Nanchang National Invitational and International Silk-Road Programming Contest C. Xyjj’s sequence(动态规划+欧拉降幂)的相关文章

The 2019 ICPC China Nanchang National Invitational and International Silk-Road Programming Contest E. Interesting Trip 长链剖分

题库链接 考虑莫比乌斯, 套上去之后就是变成了统计长度为d的一共有多少路径, 直接长链剖分, 在计蒜客上极度卡常, 卡了一万年才卡过去, 现场好像还有用点分治过去的, 这都能过?? #include<bits/stdc++.h> #define LL long long using namespace std; const int N = (int)5e5 + 7; const int M = 30000; int n, d, a[N], vis[N], miu[M + 1]; int now

The 2019 ICPC China Nanchang National Invitational and International Silk-Road Programming Contest - F.Sequence(打表+线段树)

题意:给你一个长度为$n$的数组,定义函数$f(l,r)=a_{l} \oplus a_{l+1} \oplus...\oplus a_{r}$,$F(l,r)=f(l,l)\oplus f(l,l+1)\oplus ...\oplus f(l,r)\oplus f(l+1,l+1)\oplus ...f(l+1,r)\oplus ...\oplus f(r,r)$,有两种操作,第一种将数组中某个元素$a[x]$变为$y$,第二种计算$F(l,r)$的值. 思路:打表后发现只有当$l$和$r$同

The Preliminary Contest for ICPC China Nanchang National Invitational and International Silk-Road Programming Contest

打网络赛 比赛前的准备工作要做好 确保 c++/java/python的编译器能用 打好模板,放在桌面 A. PERFECT NUMBER PROBLEM 1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 #include <se

The Preliminary Contest for ICPC China Nanchang National Invitational I题

Alice has a magic array. She suggests that the value of a interval is equal to the sum of the values in the interval, multiplied by the smallest value in the interval. Now she is planning to find the max value of the intervals in her array. Can you h

The Preliminary Contest for ICPC China Nanchang National Invitational I.Max answer单调栈

题面 题意:一个5e5的数组,定义一个区间的值为 这个区间的和*这个区间的最小值,注意数组值有负数有正数,求所有区间中最大的值 题解:如果全是正数,那就是原题 POJ2796 单调栈做一下就ok 我们现在有负数,考虑这段区间,他的和必须是负数,由于导致和为负数,最小值一定也是负数, 那对于这样一个和为负的区间进行扩展的时候,遇见下一个数,是负数,我们一定会扩展,无论这个负数大小 遇见下一个是正数,如果和没有变正,那就可以继续扩展下去(不更新答案罢了) 所以我们对于那些和为负的区间,单独统计一下答

super_log (广义欧拉降幂)(2019南京网络赛)

题目: In Complexity theory, some functions are nearly O(1)O(1), but it is greater then O(1)O(1). For example, the complexity of a typical disjoint set is O(nα(n))O(nα(n)). Here α(n)α(n) is Inverse Ackermann Function, which growth speed is very slow. So

[欧拉降幂][2019南京网络赛B]super_log

题意:输入a,b,p,求(底数a的右上角有b-1个a) 思路: 广义欧拉定理: AC代码: #include<bits/stdc++.h> typedef long long ll; using namespace std; ll a,b,m; ll vis[1000005]; ll prime[1000005],num=0; ll phi[1000005]; void getphi(ll n=1000000){ phi[1]=1; for(ll i=2;i<=n;i++){ if(!v

2019 ICPC Malaysia National G(拓扑排序)

2019 ICPC Malaysia National G 有点绕,两层拓扑排序. 有空再补详细. 甚至有点丑,因为绕,为了区分,当时变量名写得很长. #include<cstdio> #include<algorithm> #include<cstring> #include<queue> #include<vector> #define debug printf("!") using namespace std; type

2019 ICPC Malaysia National F(状态压缩)

2019 ICPC Malaysia National F 赛后补题.看了这个题解,说是状态压缩. 以第一行的士兵为主,第二行士兵为次,即,第二行被第一行士兵匹配,更新第一行士兵的状态. 用当前第i个士兵的状态更新第i+1个士兵的状态. f[i][j]:i为士兵的下标,j为第i个士兵的状态.(1<j<(1<<(e*2+1))). 比如e=3,二进制 j=1000011,表示第i个士兵之前包括第i个士兵,在[i-3,i+3]范围内,第二行的士兵已被匹配了下标为i-3,i+2,i+3的