Codeforces Round #785 (Div. 2)
A. Subtle Substring Subtraction
题目大意:A、B两人博弈,A只能删除原字符串中偶数个字符的子串,B只能删除奇数个字符的子串,a-z 被删除的得分分别是 1-26,问最终获胜的人和两人分数的差值绝对值
A先走,如果原字符串长度是偶数直接全删,如果是奇数就比较左右端点,留一个分值最小的给后手。只有字符串只有一个字母的情况下B才能赢。
#include<bits/stdc++.h>
using namespace std;
int t;
int main()
{
cin>>t;
while(t--)
{
int a=0,b=0;
string s;
cin>>s;
int len=s.size();
if(len==1)
{
cout<<"Bob"<<' '<<s[0]-'a'+1<<endl;
}
else if(len&1)
{
for(int i=0;i<len;i++)
a+=s[i]-'a'+1;
if(s[0]>s[len-1])
{
a-=s[len-1]-'a'+1;
b=s[len-1]-'a'+1;
}
else
{
a-=s[0]-'a'+1;
b=s[0]-'a'+1;
}
cout<<"Alice"<<' '<<a-b<<endl;
}
else
{
for(int i=0;i<len;i++)
a+=s[i]-'a'+1;
cout<<"Alice"<<' '<<a<<endl;
}
}
return 0;
}
B. A Perfectly Balanced String?
题目大意:给出一个字符串,问能否保证原字符串中出现的每个字母在所有原字符串的子串里出现的频率差值不大于1
这种字符串的构造方式只能是形如TTTTT( T 指的是一个内部不出现重复字符的字符串),T 的长度为一个周期。
- 找出原字符串有多少种字母
- 判断字符串是否以循环节的形式不断地出现
#include<bits/stdc++.h>
using namespace std;
set<char>setting;
int cal(string str)//统计一个字符串里有多少种字符
{
setting.clear();
for(int i=0;i<str.size();i++)
{
setting.insert(str[i]);
}
return setting.size();
}
int main()
{
int t;
cin>>t;
while(t--)
{
string s;
int ok=1;
cin>>s;
int t=cal(s);//t是循环节长度
//cout<<t<<endl;
for(int i=0;i<=s.size()-t;i++)
{
string sub=s.substr(i,t);//截取出每一个长度为t的子字符串
int temp=cal(sub);
//cout<<"i:"<<i<<' '<<temp<<endl;
if(temp!=t)//判断该子字符串内部的所有字符是否只出现一次
{
cout<<"No"<<endl;
ok=0;
break;
}
}
if(ok) cout<<"Yes"<<endl;
}
return 0;
}
C. Palindrome Basis
题目大意:将一个数字拆成若干个无前导零的回文数字(这若干个回文数字的总和为原数),求不同拆分方案的总数.
这题我当时想到应该先把表打好的,而且应该做法跟纯粹的数的拆分一样(动态规划),只是提前把回文数处理出来放到一个集合里。但是不知道动态规划怎么写,借鉴了大佬的代码,发现类似完全背包。
f
[
i
]
[
j
]
=
x
f[i][j]=x
f[i][j]=x :用前 i 种回文数字组合成 j 的方式有 x 种
状态转移:
f
[
i
]
[
j
]
=
f
[
i
]
[
j
]
+
f
[
i
−
1
]
[
j
−
f
[
i
]
]
f[i][j]=f[i][j]+f[i−1][j−f[i]]
f[i][j]=f[i][j]+f[i−1][j−f[i]]
f的维度可以压缩,所以简化成 f [ j ] = f [ j ] + f [ j − f [ i ] ] f[j]=f[j]+f[j−f[i]] f[j]=f[j]+f[j−f[i]]
#include<bits/stdc++.h>
using namespace std;
const int N = 4e4 + 1, M = 501, mod = 1e9 + 7;
int t, n, a[10], f[N], len;
vector<int> palin;
bool ispalin(int x)//判断是否是回文数
{
len = 0;
while(x)
{
a[len++] = x % 10;
x /= 10;
}
for (int i = 0; i < len; i++)
if(a[i] != a[len - i - 1])
return false;
return true;
}
int main()
{
for (int i = 1; i < N; i++)
{
if(ispalin(i))
palin.push_back(i);//预处理出回文数集合
f[i] = 1;//拆分出一个自己2333
}
for (int i = 1; i < palin.size(); i++)
for (int j = palin[i]; j < N; j++)
f[j] = (f[j] + f[j - palin[i]]) % mod;
scanf("%d", &t);
while(t--)
{
scanf("%d", &n);
printf("%d\n", f[n]);
}
return 0;
}