第一题CSL分苹果
思路:基础动态规划,设m为所有苹果的数量和,dp[x]为,容量为x时候能分的最多苹果数目,那么wavator分到的最多苹果数目就是dp[m/2],tokitsukaze分到的苹果数目就是m-dp[m/2],
下面上代码。
#include<bits/stdc++.h>
#define GET_POS(c,x) (lower_bound(c.begin(),c.end(),x)-c.begin())
#define CASET int ___T; scanf("%d", &___T); for(int cs=1;cs<=___T;cs++)
#define MP make_pair
#define PB push_back
#define MS0(X) memset((X), 0, sizeof((X)))
#define MS1(X) memset((X), -1, sizeof((X)))
#define LEN(X) strlen(X)
#define F first
#define S second
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef long double LD;
const int mod = 1e8 + 7;
const int MAXN = 1e6 + 10;
const int INF = 0x3f3f3f3f;
int dp[MAXN],a[MAXN],m,n;
int main()
{
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i],m+=a[i];
for(int i=1;i<=n;i++)
for(int j=m;j>=a[i];j--)
dp[j]=max(dp[j],dp[j-a[i]]+a[i]);
cout<<dp[m/2]<<" "<<m-dp[m/2]<<endl;
}
小埋与扫雷
思路:读懂题很重要,3bv= 周围八格没有“空格”的“数字”个数+“空"的个数。
先求周围八格没有“空格”的“数字”个数++“空"的个数。再求空的个数,这里为了方便计算,把有雷的格子标记为-1,无雷的格子标记为0,算出每个不是雷的格子的旁边八个格子有几个雷,当做这个格子的值,之后遍历每个“空格“,对每个数字进行判断,判断周围八个是否是空格。之后再dfs遍历出连通块的个数。
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3+10;
int a[maxn][maxn],m,n;
bool vis[maxn][maxn];
int bv3;
int dix[8]={-1,-1,-1,0,0,1,1,1};
int diy[8]={-1,0,1,-1,1,-1,0,1};
void dfs(int x,int y)
{
for(int i=0;i<8;i++)
{
int xx=x+dix[i],yy=y+diy[i];
if(xx>=0&&xx<n&&yy>=0&&yy<m&&a[xx][yy]==0&&!vis[xx][yy])
{
vis[xx][yy]=true;
dfs(xx,yy);
}
}
}
void sum(int x,int y)
{
for(int i=0;i<8;i++)
{
int dx=x+dix[i];
int dy=y+diy[i];
if(dx>=0&&dx<n&&dy>=0&&dy<m&&a[dx][dy]!=-1)
a[dx][dy]++;
}
}
int check(int x,int y)
{
for(int i=0;i<8;i++)
{
int xx=x+dix[i];
int yy=y+diy[i];
if(xx>=0&&xx<n&&yy>=0&&yy<m&&a[xx][yy]==0)
return 0;
}
return 1;
}
int main()
{
cin>>n>>m;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
cin>>a[i][j];
if(a[i][j])a[i][j]=-1;
}
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
if(a[i][j]==-1)sum(i,j);
}
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
if(a[i][j]!=0&&a[i][j]!=-1&&check(i,j))bv3++;
}
int it=0;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
if(a[i][j]==0&&!vis[i][j])
{
it++;
dfs(i,j);
}
}
cout<<bv3+it<<endl;
}
C. Doors Breaking and Repairing
题意:n个门,每个门有个坚固值,一个警察能拿个石头撞门每次撞X点伤害,小偷能不停的加固门,每次加固Y,问警察最多撞开几个门。
思路:题意大概是两个人玩游戏一个警察,一个坏蛋,一个人破门,一个人补门,警察像破开尽可能多的门,坏蛋想让警察破开门尽可能少,这时候就疑惑了,这到底是让我们求最大值,还是最小值?在这里我们看到,两个人的意愿也改变不了必然的结果,就拿这一组数据
6 3 2
2 3 1 3 4 2
6扇门,警察破门掉 3个耐久,坏蛋修门增加2个耐久,警察与坏蛋轮流操作,警察为破开更多的们,会选择第一次就能破开,或者说最小耐久值的门,坏蛋也是这样想的,他会修补那些一次就被警察破门的门,前提是坏蛋增加耐久大于警察破门,不然以题目这样的数据,一直撞迟早也是撞开的,当坏蛋修补增加的耐久大于警察撞门耐久时,便有了以下操作
5 5 6
1 2 6 10 3
警察第一次撞门 1
坏蛋第一次修门 2
警察第二次撞门 3
再往后警察一次撞不开一扇门,而坏蛋使门的耐久度越来越高,这就得出了必然的结果。
AC代码
#include<bits/stdc++.h>
#define GET_POS(c,x) (lower_bound(c.begin(),c.end(),x)-c.begin())
#define CASET int ___T; scanf("%d", &___T); for(int cs=1;cs<=___T;cs++)
#define MP make_pair
#define PB push_back
#define MS0(X) memset((X), 0, sizeof((X)))
#define MS1(X) memset((X), -1, sizeof((X)))
#define LEN(X) strlen(X)
#define F first
#define S second
using namespace std;
typedef long long ll;
typedef unsigned long long ULL;
typedef long double LD;
const int mod = 1e8 + 7;
const int MAXN = 1e6 + 10;
const int INF = 0x3f3f3f3f;
int a[MAXN],n,x,y,ans;
int main()
{
cin>>n>>x>>y;
for(int i=1;i<=n;i++)
{
cin>>a[i];
if(a[i]<=x)ans++;
}
if(x>y)cout<<n<<endl;
else {
if(ans&1)cout<<ans/2+1<<endl;
else cout<<ans/2<<endl;
}
}
Key Set
思路:多写两组数据就能看出来公式就是sum=2^(n-1)-1,直接快速幂不解释
AC代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ULL;
typedef long double LD;
const int mod = 1000000007;
const int MAXN = 1e6 + 10;
const int INF = 0x3f3f3f3f;
ll qpow(ll a,ll b)
{
ll res=1;
while(b)
{
if(b&1)res=(res*a)%mod;
b=b/2;
a=a*a%mod;
}
res=res%mod;
return res;
}
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
cout<<qpow(2,n-1)-1<<endl;
}
}
D. Balanced Ternary String
题意:一串只包含012且长度为n的字符串,然后让你替换字符,使得在替换的次数最少的前提下,使得新获得的字符串中0,1,2这三个字 符的数目相同,并且新获得的字符串字典序要尽可能的小。
思路:首先考虑贪心,三种情况
0多的时候,从后往前遍历,依次补2,补1
1多的时候,补2的时候从后往前遍历,补0的时候从前往后遍历
2多的时候,从前往后遍历,依次补0,补1。
另外在cf使用io流输入时候好像不能使用这一句。开始一直WA,后来把这句话去掉就A了,具体原因不清楚
ios::sync_with_stdio(false);
AC代码
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e6 + 10;
const int INF = 0x3f3f3f3f;
char str[MAXN];
int mmp[4];
int main()
{
int n;
cin>>n;
scanf("%s",str);
for(int i=0;i<n;i++)
mmp[str[i]-'0']++;
int now=n/3;
if(mmp[0]>now)
{
for(int i=n-1;i>=0;i--)
{
if(str[i]=='0')
{
if(mmp[2]<now&&mmp[0]>now)
{
str[i]='2';
mmp[2]++;
mmp[0]--;
}
else if(mmp[1]<now&&mmp[0]>now)
{
str[i]='1';
mmp[1]++;
mmp[0]--;
}
}
}
}
if(mmp[1]>now)
{
for(int i=0;i<n;i++)
{
if(str[i]=='1')
{
if(mmp[0]<now&&mmp[1]>now)
{
str[i]='0';
mmp[0]++;
mmp[1]--;
}
}
}
for(int i=n-1;i>=0;i--)
{
if(str[i]=='1')
{
if(mmp[2]<now&&mmp[1]>now)
{
str[i]='2';
mmp[2]++;
mmp[1]--;
}
}
}
}
if(mmp[2]>now)
{
for(int i=0;i<n;i++)
{
if(str[i]=='2')
{
if(mmp[0]<now&&mmp[2]>now)
{
str[i]='0';
mmp[0]++;
mmp[2]--;
}
else if(mmp[1]<now&&mmp[2]>now)
{
str[i]='1';
mmp[1]++;
mmp[2]--;
}
}
}
}
printf("%s\n",str);
}