东华大学2020年程序设计竞赛(同步赛)(D 暴力 F 博弈论 G dp)

题目链接

D-Moving stones

题意:给你n个石子堆,每堆初始有a[i]个石子,每次选择一堆石子,将其他的的n-1个石子 各拿一个给这堆。问多次这样的操作能否使得所有的石子堆个数相同。

做法:n只有,暴力模拟几千数据左右就可以了。每次选最小石子堆。。。想优化想了半天,没想到是这样的做法

#include<bits/stdc++.h>
#define ll long long
using namespace std;

const int maxx=1e3+100;
int a[maxx];
vector<int> v;
int n;

int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);
		for(int i=1;i<=n;i++) scanf("%d",&a[i]);
		sort(a+1,a+1+n);
		int sum=0;
		for(int i=1;i<=n;i++) sum+=a[i];
		if(sum%n) cout<<"No"<<endl;
		else
		{
			v.clear();
			for(int i=1;i<=n;i++) v.push_back(a[i]);
			int flag=0;
			int cnt=0;
			while(cnt<=1500)
			{
				sort(v.begin(),v.end());
				if(v[0]==v.back()) 
				{
					flag=1;
					break;
				}
				if(v[1]==0) break;//出现0了,说明就要变成负数了,这样肯定不行。
				v[0]+=(n-1);
				for(int i=1;i<n;i++) v[i]--;
				cnt++;
			}
			if(flag==0) cout<<"No"<<endl;
			else cout<<"Yes"<<endl;
		}
	}
	return 0;
}

F-A Simple Game

题意:给你n个只包含01的字符串,Bob和Alice轮流玩游戏,Alice先手,每次操作:

选择任意几个字符串,每个字符串可以进行以下两个操作

1、选择长度大于2的连续0串,用1代替,

2、选一个1字符,将其变为0

谁最后无法移动就输了

做法:每次操作发现都是改变了一个串中1的个数。偶数->奇数  奇数->偶数 

结论:若所有字符串1的个数为偶数,后手必胜

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define ll long long
#define maxn 1005
#define inf 1e9
#define pb push_back
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
 
inline ll read()
{
    ll x=0,w=1; char c=getchar();
    while(c<'0'||c>'9') {if(c=='-') w=-1; c=getchar();}
    while(c<='9'&&c>='0') {x=(x<<1)+(x<<3)+c-'0'; c=getchar();}
    return w==1?x:-x;
}
const int N=1e3+10;
char s[N];
int main()
{
    int _=read();while(_--)
    {
        int n=read(),flag=1;
        rep(i,1,n)
        {
            scanf("%s",s+1);
            int len=strlen(s+1);
 
            int ans=0;
            rep(j,1,len) ans+=s[j]-'0';
            if(ans%2) flag=0;
        }
        printf("%s\n",flag?"kgNB":"sdzNB");
    }
}

G-Gaming with Mia

题意:给你n个数,你可以在n-1个间隔之间填+  或 *  使得表达式尽量最大。

n个数范围:[-1,1]

做法:dp,dp[i][j] 代表前i个数,当前尾部的数为j时的最大值。加法的话,尾部依旧是a[i]  乘法的话  尾部就是 a[i]*j

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define ll long long
#define maxn 1005
#define pb push_back
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
using namespace std;

inline ll read()
{
	ll x=0,w=1; char c=getchar();
	while(c<'0'||c>'9') {if(c=='-') w=-1; c=getchar();}
	while(c<='9'&&c>='0') {x=(x<<1)+(x<<3)+c-'0'; c=getchar();}
	return w==1?x:-x;
}
const int N=1e5+10,inf=1e9;
int dp[N][3],a[N],n;
void up(int &x,int y)
{
    x=max(x,y);
}
int main()
{
    int _=read();while(_--)
    {
        n=read();
        rep(i,1,n) a[i]=read();

        rep(j,0,2) dp[1][j]=-inf;

        dp[1][a[1]+1]=a[1];
        rep(i,2,n)
        {
            rep(j,0,2) dp[i][j]=-inf;

            rep(j,-1,1){
                up(dp[i][a[i]+1],dp[i-1][j+1]+a[i]);
                up(dp[i][j*a[i]+1],dp[i-1][j+1]+j*a[i]-j);
            }
        }
        printf("%d\n",max({dp[n][0],dp[n][1],dp[n][2]}));

    }
}

猜你喜欢

转载自blog.csdn.net/qq_41286356/article/details/106618019