《东华大学2020年程序设计竞赛题解》

D:

思路:模拟.

因为n的数量比较小。所以可以去模拟这个操作.

每次给最小的加上n-1,其他的减去1.当a[1] < 0时说明不合法.

当a[1] = a[n]时说明可以实现。

因为a[n]的值在[0,1000],所以很明显这个模拟次数最多1000次.

当1000次还没退出时说明在这之前肯定出现过重复状态.那么说明是无法实现的.

Code:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
const int N = 1e5+5;
const int M = 1e6+5;
const int Mod = 1e9+7;
#define pi acos(-1)
#define INF 1e8
#define INM INT_MIN
#define pb(a)  push_back(a)
#define mk(a,b) make_pair(a,b)
#define dbg(x) cout << "now this num is " << x << endl;
#define met0(axx) memset(axx,0,sizeof(axx));
#define metf(axx) memset(axx,-1,sizeof(axx));
#define sd(ax) scanf("%d",&ax)
#define sld(ax) scanf("%lld",&ax)
#define sldd(ax,bx) scanf("%lld %lld",&ax,&bx)
#define sdd(ax,bx) scanf("%d %d",&ax,&bx)
#define sddd(ax,bx,cx) scanf("%d %d %d",&ax,&bx,&cx)
#define sfd(ax) scanf("%lf",&ax)
#define sfdd(ax,bx) scanf("%lf %lf",&ax,&bx)
#define pr(a) printf("%d\n",a)
#define plr(a) printf("%lld\n",a)
int a[105];
void slove()
{
    int t;sd(t);
    while(t--)
    {
        int n,sum = 0;sd(n);
        for(int i=1;i<=n;++i) sd(a[i]),sum += a[i];
        if(sum%n != 0) printf("No\n");
        else
        {
            sort(a+1,a+n+1);
            bool f = false;
            for(int i=1;i<=1000;++i)
            {
                if(a[1] == a[n]) {f = true;break;}
                if(a[1] < 0) break;
                a[1] += n-1;for(int j=2;j<=n;++j) a[j]--;
                sort(a+1,a+n+1);
            }
            printf("%s\n",f ? "Yes" : "No");
        }
    }
}  
int main()
{
    slove();
   // system("pause");
    return 0;
}
View Code

F:博弈论

思路:

可以发现对于0的操作,可以看成无效。

因为先手将00变成1,后手可以直接将他变成0.这样操作相当于无效。

所以只有原来的1的个数会影响结果。

那么显然当原来串中1的个数为奇数个时,先手必赢,反之后手必赢.

Code:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
const int N = 1e5+5;
const int M = 1e6+5;
const int Mod = 1e9+7;
#define pi acos(-1)
#define INF 1e8
#define INM INT_MIN
#define pb(a)  push_back(a)
#define mk(a,b) make_pair(a,b)
#define dbg(x) cout << "now this num is " << x << endl;
#define met0(axx) memset(axx,0,sizeof(axx));
#define metf(axx) memset(axx,-1,sizeof(axx));
#define sd(ax) scanf("%d",&ax)
#define sld(ax) scanf("%lld",&ax)
#define sldd(ax,bx) scanf("%lld %lld",&ax,&bx)
#define sdd(ax,bx) scanf("%d %d",&ax,&bx)
#define sddd(ax,bx,cx) scanf("%d %d %d",&ax,&bx,&cx)
#define sfd(ax) scanf("%lf",&ax)
#define sfdd(ax,bx) scanf("%lf %lf",&ax,&bx)
#define pr(a) printf("%d\n",a)
#define plr(a) printf("%lld\n",a)
int check(string s)
{
    int sum = 0;
    for(int i=0;i<s.size();++i)
    {
        if(s[i] == '1') sum++;
    }
    if(sum&1) return 1;
    return 0;
}
void slove()
{
    int t;sd(t);
    while(t--)
    {
        int n,cnt = 0;sd(n);
        while(n--)
        {
            string s;cin >> s;
            if(check(s)) cnt++;
        }
        if(cnt != 0) printf("sdzNB\n");
        else printf("kgNB\n");
    }
}  
int main()
{
    slove();
   // system("pause");
    return 0;
}
View Code

 

G:

显然对于1,我们去加它更好优.

我们考虑结果为若干个乘积相加的形式.

两个数连乘
-1 -1 -1*-1 = 1比加优
三个数连乘
-1 1 -1 -1*-1*1 = 1比加优
四个数连乘
-1 1 1 -1 -1*1*-1*1 = 1比加优.
五个数连乘
-1 1 1 1 -1 加和乘一样.
 
6..7...8都不再有乘比加优的情况.
说明最多出现四个数连乘的状态.
那么定义dp[i][2].
dp[i][0] - 表示和前面一个数相乘,到i位置的最大价值.
dp[i][1] - 表示和前面一个数相加,到i位置的最大价值.
转移:
对于相加很简单
dp[i][1] = max(dp[i-1][1]+a[i],dp[i-1][0]+a[i]);
对于相乘枚举两个数相乘.三个数相乘.四个数相乘。更新dp[i][0].
Code:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
const int N = 1e5+5;
const int M = 1e6+5;
const int Mod = 1e9+7;
#define pi acos(-1)
#define INF 1e8
#define INM INT_MIN
#define pb(a)  push_back(a)
#define mk(a,b) make_pair(a,b)
#define dbg(x) cout << "now this num is " << x << endl;
#define met0(axx) memset(axx,0,sizeof(axx));
#define metf(axx) memset(axx,-1,sizeof(axx));
#define sd(ax) scanf("%d",&ax)
#define sld(ax) scanf("%lld",&ax)
#define sldd(ax,bx) scanf("%lld %lld",&ax,&bx)
#define sdd(ax,bx) scanf("%d %d",&ax,&bx)
#define sddd(ax,bx,cx) scanf("%d %d %d",&ax,&bx,&cx)
#define sfd(ax) scanf("%lf",&ax)
#define sfdd(ax,bx) scanf("%lf %lf",&ax,&bx)
#define pr(a) printf("%d\n",a)
#define plr(a) printf("%lld\n",a)
/*
考虑结果为若干个乘积相加的形式.
两个数连乘
-1 -1 -1*-1 = 1比加优
三个数连乘
-1 1 -1 -1*-1*1 = 1比加优
四个数连乘
-1 1 1 -1 -1*1*-1*1 = 1比加优.
五个数连乘
-1 1 1 1 -1 加和乘一样.
*/
int a[N];
int dp[N][2];//和前面的乘,和前面的加.
void slove()
{
    int t;sd(t);
    while(t--)
    {
        met0(dp);
        int n;sd(n);
        for(int i=1;i<=n;++i) sd(a[i]);
        dp[1][0] = dp[1][1] = a[1];
        for(int i=2;i<=n;++i)
        {
            dp[i][0] = max(dp[i][0],max(dp[i-2][1]+a[i-1]*a[i],dp[i-2][0]+a[i-1]*a[i]));//两个连乘
            if(i >= 3) dp[i][0] = max(dp[i][0],max(dp[i-3][1]+a[i-2]*a[i-1]*a[i],dp[i-3][0]+a[i-2]*a[i-1]*a[i]));//三个连乘
            if(i >= 4)//四个连乘
            {
                int t1 = dp[i-4][0]+a[i-3]*a[i-2]*a[i-1]*a[i];
                int t2 = dp[i-4][1]+a[i-3]*a[i-2]*a[i-1]*a[i];
                dp[i][0] = max(dp[i][0],max(t1,t2));
            }
            dp[i][1] = max(dp[i][1],dp[i-1][1]+a[i]);
            dp[i][1] = max(dp[i][1],dp[i-1][0]+a[i]);
        }
        pr(max(dp[n][1],dp[n][0]));
    }
}  
int main()
{
    slove();
    system("pause");
    return 0;
}
/*
-1 1 -1 -1*1*-1 = 1
-1 1 1 -1  -1*1*1*-1 = 1
-1 1 1 1 -1
*/
View Code

 

 

posted @ 2020-06-08 17:07  levill  阅读(330)  评论(0编辑  收藏  举报