The 2022 ICPC Asia Hangzhou Regional Programming Contest

比赛连接:Dashboard - The 2022 ICPC Asia Hangzhou Regional Programming Contest - Codeforces

A. Modulo Ruins the Legend

题目大意:

给你一个长度为n的数组,确定s,d的值,对于数组第k个元素ak加上s+kd,k∈[1,n],使得加上后数组的和模m后值最小。

0<=s

n,m (1≤n≤10^5, 1≤m≤10^9).

思路:

The 2022 ICPC Asia Hangzhou Regional Programming Contest_第1张图片

代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include
#include 
#include 
#define pii pair
#define pll pair
#define pil pair
#define pli pair
#define pdd pair
#define se second 
#define fi first
#define endl '\n'
#define rep(i,a,b) for (register int i=a;ib;--i)
#define MEM(a,x) memset(a,x,sizeof(a))
#define M(x) ((x)%MOD)
#define db double
#define eps 1e-9
typedef long long LL;
typedef unsigned long long ULL;
using namespace std;
const int MOD=9901;
const int N=25;
int gcd(int a,int b)
{
	if(!b) return a;
	return gcd(b,a%b);
}
int exgcd(int a,int b,int &x,int &y)
{
	if(!b){
		x=1,y=0;
		return a;
	}
	int d=exgcd(b,a%b,y,x);
	y-=a/b*x;
	return d;
}
void solve()
{
	int n,m,x,y,sum=0;
	cin>>n>>m;
	rep(i,0,n){
		cin>>x;
		sum=(sum+x)%m;
	}
	int s,d;
	int g0=exgcd(n%m,1ll*n*(n+1)/2%m,s,d);
	if(sum==0||g0==0){
		cout<<0<t){
			ans=t;
			break;
		}
		t%=g;
	}
	int T=((ans-sum)%m+m)%m;
	g=exgcd(g0,m,x,y);
	x=1ll*x*T/g%m;
	x=(x+m)%m;
	s=1ll*s*x%m,d=1ll*d*x%m;
	s=(s+m)%m,d=(d+m)%m;
	cout<>_; 
	while(_--){
		solve();
	}
	return 0;
}

C. No Bug No Game

题目大意:

给定n个物品和限定k,要求最大化分数。物品的选择顺序可以任意。

第i物品一行pi代表个数,后面pi个wij代表容量(不一定递增),记录sum为∑pj (1≤j

  • sum+pi≤k 得到w(i,pi)的分
  • sum≥k, 不能再加分了。
  • 否则得到w(i,k−sum)分。

1≤n≤3000, 0≤k≤3000

1≤pi≤10;1≤wi,j≤10^5

思路:

简单的背包问题变型,可以将sum看做是背包容量,在k之内做动态规划。区别就是如果sum+pi>k,就会有一个物品不选满(选到刚好达到k的容量并得到相应的价值)。

用f[i][j][z]表示从前i个物品当中选,总和刚好为j,且z=0表示所有物品选满,z=1表示有一个没有选满的物品。转移方程见代码。

最后在枚举更新答案的时候需要判断j==k的时候才可以更新f[i][j][1]这个情况。

代码: 

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include
#include 
#include 
#define pii pair
#define pll pair
#define pil pair
#define pli pair
#define pdd pair
#define se second 
#define fi first
#define endl '\n'
#define rep(i,a,b) for (register int i=a;ib;--i)
#define MEM(a,x) memset(a,x,sizeof(a))
#define M(x) ((x)%MOD)
#define db double
#define eps 1e-9
typedef long long LL;
typedef unsigned long long ULL;
using namespace std;
const int MOD=9901;
const int N=3005;
int f[N][N][2],w[15];
void solve()
{
	int n,k,p;
	cin>>n>>k;
	MEM(f,-0x3f);
	f[0][0][0]=0;
	rep(i,1,n+1){
		cin>>p;
		rep(j,1,p+1) cin>>w[j];
		per(j,k-1,-1){
			f[i][j][0]=f[i-1][j][0];
		    f[i][j][1]=f[i-1][j][1];
		    if(j+p<=k) f[i][j+p][0]=max(f[i][j+p][0],f[i-1][j][0]+w[p]),f[i][j+p][1]=max(f[i][j+p][1],f[i-1][j][1]+w[p]);
		    rep(z,1,p) if(j+z<=k) f[i][j+z][1]=max(f[i][j+z][1],f[i-1][j][0]+w[z]);
		}
	}
	int ans=0;
	rep(i,1,n+1) rep(j,0,k+1){
		ans=max(ans,f[i][j][0]);
		if(j==k) ans=max(ans,f[i][j][1]);
	}
	cout<>_; 
	while(_--){
		solve();
	}
	return 0;
}

D. Money Game

题目大意:

n个人玩游戏,第i个人初始值为ai;每一轮会进行:从前往后,前一个人把他的值一半给后一个人,最后一个会给第一个。

问经过2022^1204轮之后,输出每个人的值,误差在10^-6之内。

2≤n≤10^5

1≤ai≤10^6

思路:

打表可以看出经过很多轮次后,最后满足a1=2*a2=...=2*an,而且整个序列的和不会因为操作而改变。数值的和记为s,当次数趋于无穷时,第一个数为2s/(n+1),后面都是s/(n+1)。

代码: 

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include
#include 
#include 
#define pii pair
#define pll pair
#define pil pair
#define pli pair
#define pdd pair
#define se second 
#define fi first
#define endl '\n'
#define rep(i,a,b) for (register int i=a;ib;--i)
#define MEM(a,x) memset(a,x,sizeof(a))
#define M(x) ((x)%MOD)
#define db double
#define eps 1e-9
typedef long long LL;
typedef unsigned long long ULL;
using namespace std;
const int MOD=9901;
const int N=25;
void solve()
{
	int n;
	db s=0;
	cin>>n;
	rep(i,0,n){
		db x;
		cin>>x;
		s+=x;
	}
	s/=(n+1);
	rep(i,0,n) if(i) printf("%.7lf ",s); else printf("%.7lf ",2*s);
}
int main()
{
//	#ifndef ONLINE_JUDGE
//		freopen("title.in","r",stdin);
//		freopen("title.out","w",stdout);
//	#endif
	//ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int _=1;
	//cin>>_; 
	while(_--){
		solve();
	}
	return 0;
}

E. Oscar is All You Need

题目大意:

T组测试,每组给定一个n,和1-n的排列,可以最多操作2*n+1次,每次操作将数组分为非空的三个部分,交换第一个和第三个部分。问字典序最小序列。输出操作次数和方案。(不要求操作次数最小)

1≤T≤120

3≤n≤1000

思路:

The 2022 ICPC Asia Hangzhou Regional Programming Contest_第2张图片

 The 2022 ICPC Asia Hangzhou Regional Programming Contest_第3张图片

 The 2022 ICPC Asia Hangzhou Regional Programming Contest_第4张图片

代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include
#include 
#include 
#define pii pair
#define pll pair
#define pil pair
#define pli pair
#define pdd pair
#define se second 
#define fi first
#define endl '\n'
#define rep(i,a,b) for (register int i=a;ib;--i)
#define MEM(a,x) memset(a,x,sizeof(a))
#define M(x) ((x)%MOD)
#define db double
#define eps 1e-9
typedef long long LL;
typedef unsigned long long ULL;
using namespace std;
const int MOD=9901;
const int N=1010;
int n,a[N],b[N],sz;
pii p[2*N+5];
int got(int x)
{
	rep(i,1,n+1) if(a[i]==x) return i;
}
void op(int l,int r)
{
	p[++sz]={l-1,n-r};
	int cnt=0;
	rep(i,r+1,n+1) b[++cnt]=a[i];
	rep(i,l,r+1) b[++cnt]=a[i];
	rep(i,1,l) b[++cnt]=a[i];
	rep(i,1,n+1) a[i]=b[i];
}
void solve()
{
	cin>>n;
	rep(i,1,n+1) cin>>a[i];
	if(n==3){
		if(a[1]>a[3]) cout<<1<>_; 
	while(_--){
		solve();
	}
	return 0;
}

F. Da Mi Lao Shi Ai Kan De

题目大意:

有n各组,每组给一些字符串,从组中选择含有字串"bie"的加入到一组中(如果存在了不加了),如果可以添加就输出这个字符串,否则输出“Time to play Genshin Impact, Teacher Rice!”

思路:

水题,用string和set模拟即可。

代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include
#include 
#include 
#define pii pair
#define pll pair
#define pil pair
#define pli pair
#define pdd pair
#define se second 
#define fi first
#define endl '\n'
#define rep(i,a,b) for (register int i=a;ib;--i)
#define MEM(a,x) memset(a,x,sizeof(a))
#define M(x) ((x)%MOD)
#define db double
#define eps 1e-9
typedef long long LL;
typedef unsigned long long ULL;
using namespace std;
const int MOD=9901;
const int N=25;
setst;
void solve()
{
	int n;
	bool f=0;
	cin>>n;
	while(n--){
		string s;
		cin>>s;
		if(s.find("bie")!=-1&&st.find(s)==st.end()){
			cout<>_; 
	while(_--){
		solve();
	}
	return 0;
}

K. Master of Both

题目大意:

给定n个字符串,q此询问,每一次询问都定义一个字母字典序大小规则,在这种大小规则下求n个字符串逆序对的个数。

1≤n≤5×10^5, 1≤q≤5×10^4
The 2022 ICPC Asia Hangzhou Regional Programming Contest_第5张图片

思路:

在比较两个字符串的时候,只需要比较第一个不相同字母的大小就可以了。建立trie树,在建树的过程中维护cnt[p]的值,表示以p为前缀的字符串个数。再用inv[i][j]记录序列中(j,i)的对数个数。

注意有一种特殊情况需要单独算:当一个字符串插入完后,要加上其所有的子节点。因为它可能是前面字符串的一个前缀,这种情况它一定会和这些字符串构成逆序对。

最后计算答案就是两重循环,每次加上预处理出来的inv[i][j] (j>i)即可。

代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include
#include 
#include 
#define pii pair
#define pll pair
#define pil pair
#define pli pair
#define pdd pair
#define se second 
#define fi first
#define endl '\n'
#define rep(i,a,b) for (register int i=a;ib;--i)
#define MEM(a,x) memset(a,x,sizeof(a))
#define M(x) ((x)%MOD)
#define db double
#define eps 1e-9
typedef long long LL;
typedef unsigned long long ULL;
using namespace std;
const int MOD=1e9+7;
const int N=1e6+10;
int tr[N][26],idx=1;
LL tot,cnt[N],inv[26][26];
string s;
void ins()
{
	int p=1;
	++cnt[p];
	rep(i,0,s.size()){
		int j=s[i]-'a';
		rep(k,0,26) if(j!=k) inv[j][k]+=cnt[tr[p][k]];
		if(tr[p][j]==0) tr[p][j]=++idx;
		p=tr[p][j],++cnt[p];
	}
	rep(i,0,26) tot+=cnt[tr[p][i]];
}
void solve()
{
	int n,q;
	cin>>n>>q;
	while(n--){
		cin>>s;
		ins();
	}
	while(q--){
		LL ans=0;
		cin>>s;
		rep(i,0,s.size()) rep(j,i+1,s.size()) ans+=inv[s[i]-'a'][s[j]-'a'];
		cout<>_; 
	while(_--){
		solve();
	}
	return 0;
}

开坑开坑~~~

由于期末考试压力,其他题目待补题qwq,后面会持续更新~

你可能感兴趣的:(ACM-ICPC)