链接:http://codeforces.com/contest/1025
远离pupil,从我做起。
目录
A.Doggo Recoloring
题目
给定一个字符串,字符串任意一个出现>=2次的字符都可以集体被替换成另一个,比如“abababc”可以变成"zbzbzbc", "bbbbbbc", "aaaaaac", "acacacc",但不能变换最后一个c,因为它只出现了一次。给一个字符串,问能否通过若干次上述变换,使得字符串里每个字符都一样。
题解
至少有一个出现次数>=2的字符即可。当然字符串长度为1的情况要特殊考虑一下。
代码
#include <bits/stdc++.h>
using namespace std;
#define INIT(x) memset(x,0,sizeof(x))
#define eps 1e-8
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int maxn = 200005;
inline void read(int &x)
{
int f=1;x=0;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
x*=f;
}
inline void print(int x)
{
if(x<0){ putchar('-'); x=-x;}
if(x>9) print(x/10);
putchar(x%10+'0');
}
inline void caltime(int tt) {
tt = clock() - tt;
cerr << (double)tt/CLOCKS_PER_SEC << " seconds!" << endl;
}
int n;
string s;
int a[100];
int main()
{
cin>>n>>s;
for(int i=0;i<n;i++) {
int temp = s[i]-'a';
a[temp]++;
}
int ans = 0;
for(int i=0;i<26;i++) {
if(a[i]>=2) {
ans++;
}
}
if(ans||n==1) {
cout<<"Yes"<<endl;
}else {
cout<<"No"<<endl;
}
return 0;
}
B. Weakened Common Divisor
题目
给n组数据,每组有一个a和b,要求一个公约数x,使得每组的a和b至少有一个含有这个约数x。如果x为1的话输出-1,否则输出x。(x可能有多个,随便输出一个就行了)
题解
什么神题这都是。。。
这题最难处理的地方在于,每组有两个数,只要任意一个的公约数满足就行了。于是我写了个DFS,果然TLE了- -
(看一下代码吧)
#include <bits/stdc++.h>
using namespace std;
#define INIT(x) memset(x,0,sizeof(x))
#define eps 1e-8
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int maxn = 150005;
inline void read(int &x)
{
int f=1;x=0;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
x*=f;
}
int gcd(int a,int b) {
if(b==0) return a;
return gcd(b,a%b);
}
int n;
int a[maxn],b[maxn];
int tot1,tot2,tot;
void dfs(int x,int ans) {
if(x==n-1) {
tot = ans;
return;
}
for(int i=0;i<2;i++) {
if(i&1) {
int temp = gcd(a[x+1],ans);
if(temp==1) {
return;
}else {
dfs(x+1,temp);
}
}else {
int temp = gcd(b[x+1],ans);
if(temp==1) {
return;
}else {
dfs(x+1,temp);
}
}
}
}
int main()
{
cin>>n;
for(int i=0;i<n;i++) {
read(a[i]);
read(b[i]);
}
dfs(0,a[0]);
tot1 = tot;
if(tot<=0) {
tot = 0;
dfs(0,b[0]);
}
if(tot<=0) {
cout<<-1<<endl;
} else{
cout<<tot<<endl;
}
return 0;
}
每组a和b的因数不同,但是如果把a和b的因数全都放到一块,问题就解决啦。
于是,我们要求每组a和b的最小公倍数!!!然后再用一个x,与所有组的最小公倍数求最大公约数。
这样之后,x含有的因数必然是所有组的因数之一。 但是x本身可能会超出范围,因为它是若干组因数的乘积。于是就有了解法1.
#include <bits/stdc++.h>
using namespace std;
#define INIT(x) memset(x,0,sizeof(x))
#define eps 1e-8
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int maxn = 150005;
ll gcd(ll a,ll b) {
if(b==0) return a;
return gcd(b,a%b);
}
ll n;
ll a,b;
ll tot1,tot2,tot;
int main()
{
cin>>n;
ll x = 0;
for(int i=0;i<n;i++) {
scanf("%lld%lld",&a,&b);
a = a/gcd(a,b)*b;
x = gcd(x,a);
}
if(x==1) {
cout<<-1<<endl;
return 0;
}
for(int i=2;i*i<=x;i++) {
//cout<<i<<endl;
if(x%i==0) {
cout<<i<<endl;
return 0;
}
}
cout<<x; //如果x没有大于1的因数,说明它是个素数,但由于它肯定符合条件,直接输出x就行了
return 0;
}
这时候,遇到了神仙数据
2 1999999973 1999999943 1999999973 1999999943
这个数求出来的x是1e18的,开了根号也是1e9,会TLE,只能改进做法了。
我们用x重新与每组的a和b都去求最大公约数,并取其较大值。因为在x!=1的情况下,说明肯定存在解,而且之前说过了,x的所有>1的因数必然是正解,那么取较大的解肯定没错。(也可以不取较大解,只要取公约数>1的解就行了。)
for(int i=0;i<n;i++) {
if(gcd(x,a[i])>1) {
x = gcd(x,a[i]);
}
if(gcd(x,b[i])>1) {
x = gcd(x,b[i]);
}
}
for(int i=0;i<n;i++) {
x = max(gcd(x,a[i]),gcd(x,b[i]));
}
以上的两种写法都是对的。
C.Plasticine zebra
题目
给一个字符串,只由b和w组成,现在可以进行若干次操作,每次操作可以选择一个位置,使这个位置左右两边的字符串都倒过来。
举个栗子,”bw | bbw“ 变成 "wb | wbb"。一个字符串的最大价值记为该字符串中最长的交替串(即"bwbwbw"这类的),问怎么样才能使价值最大,求最大价值。
题解
我们用数组c来记录,如果一个字符和其后面一个字符相等,那么值为0,否则值为1,最后一个字符看成一个环,它的下一个字符就是第一个字符。
由于翻转操作,如果字符串wbwbbbwb,那么对于数组c的值是11100111,我们可以把开头3个1和结尾3个1连起来,方法就是以开头第(3+1)个位置为分界旋转。
无论怎么变换,结尾和开头的元素经过翻转后必然会碰到一块。同理,相邻的两个元素,一次翻转后会变成开头结尾,再次翻转又会相邻。
如果c数组为0110110(对应wwbwwbw) ,那么这两块1是无论如何也拼不到一起的。
原问题便转化成了,求一个环中连续1的最大长度。
代码
#include <bits/stdc++.h>
using namespace std;
#define INIT(x) memset(x,0,sizeof(x))
#define eps 1e-8
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int maxn = 200005;
inline void read(int &x)
{
int f=1;x=0;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
x*=f;
}
inline void print(int x)
{
if(x<0){ putchar('-'); x=-x;}
if(x>9) print(x/10);
putchar(x%10+'0');
}
inline void caltime(int tt) {
tt = clock() - tt;
cerr << (double)tt/CLOCKS_PER_SEC << " seconds!" << endl;
}
string s;
int c[maxn];
int main()
{
cin>>s;
int n = s.length();
for(int i=0;i<n;i++) {
c[i] = (s[i]!=s[(i+1)%n]);
}
int s = 1,ans = 1;
for(int i=0;i<2*n;i++) {
if(c[i%n]==0) s = 1;
else {
s++;
ans = max(ans,s);
}
}
if(ans>=n)
ans = n;
cout<<ans<<endl;
return 0;
}