回归之旅,怎么能少了cf,从div3开始玩起,又是一年多没玩的游戏了,赶紧上手找找感觉,题目不难,最重要的就是自信与时间的把握,确实太久没做题了
A. Circle of Students
思路:简单判循环题,正反两下循环即可搞定,手太生了,连循环都不敢写了
#include <bits/stdc++.h>
using namespace std;
#define ne ((i+1)%n)
#define la ((i+n-1)%n)
const int maxn = 210;
int a[maxn];
int main()
{
int q;
scanf("%d",&q);
while(q--)
{
int n;
scanf("%d",&n);
int st = -1;
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
if(a[i]==1)
{
st = i;
}
}
//cout << st <<endl;
if(st == -1) printf("NO\n");
else if(n==1) printf("YES\n");
else
{
if(a[((st+1)%n)]==2)
{
bool ok = true;
for(int i=st;ok&&(i!=((st+n-1)%n));i=ne)
{
//cout << i << "@" << ne << "@" << a[i] << "@" << a[ne] << endl;
if(a[i]!=a[ne]-1) ok = false;
}
if(ok) printf("YES\n");
else printf("NO\n");
}
else if(a[((st+n-1)%n)]==2)
{
bool ok = true;
for(int i=st;ok&&(i!=((st+1)%n));i=la)
{
if(a[i]!=a[la]-1) ok = false;
}
if(ok) printf("YES\n");
else printf("NO\n");
}
else printf("NO\n");
}
}
return 0;
}
B. Equal Rectangles
思路:给定特定边,判断能否组成n个面积相等的矩形,由于面积乘法公式的单调性,直接暴力开乘,注意一下边界即可
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1100;
int a[maxn];
int main()
{
int q;
scanf("%d",&q);
while(q--)
{
int n;
scanf("%d",&n);
for(int i=0;i<4*n;i++) scanf("%d",&a[i]);
sort(a,a+4*n);
int st = 0;
int en = 4*n-1;
bool ok = true;
if(a[st+1]!=a[st]||a[en-1]!=a[en]) ok = false;
int sq = a[st] * a[en];
for(st+=2,en-=2;ok&&st<en;st+=2,en-=2)
{
if(a[st+1]!=a[st]||a[en-1]!=a[en]) ok = false;
if(sq != a[st] * a[en]) ok = false;
}
if(ok) printf("YES\n");
else printf("NO\n");
}
return 0;
}
C. Common Divisors
思路:求n个数的公因数个数,如此水题居然把我困住了,公因数个数先求最大公因数,然后将最大公因数分解即可。还是手太生疏了
#include <bits/stdc++.h>
using namespace std;
int countfactor(long long n)
{
int sum=1;
for(long long i=2;i<=(long long)(sqrt(double(n))+1LL);i++)
{
int cnt=0;
while(n%i==0)
{
n/=i;
cnt++;
}
sum*=(cnt+1);
}
if(n>1LL)
sum*=2;
return sum;
}
int main()
{
int n;
long long a;
long long res;
scanf("%d",&n);
scanf("%I64d",&res);
for(int i=1;i<n;i++)
{
scanf("%I64d",&a);
res = __gcd(res,a);
}
printf("%d\n",countfactor(res));
return 0;
}
D2. Remove the Substring (hard version)
思路:D1简单版我就跳过了,hard版过简单版。
在保证匹配的情况下,求母串可删的最长长度
这就是个字符串双扫描问题,第一次扫描将子串与母串映射,由于第二次扫描具有单调性,实现起来完全ok,最后考虑一下两端边界就ok了。其实现在最大的问题就是自己内心的惧怕,看似很复杂,其实并不会很难,而在于自己内心的自信以及对时间的把握上
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5+10;
char s[maxn];
char t[maxn];
int pos[maxn];
int main()
{
scanf("%s%s",s,t);
int sl = strlen(s), tl = strlen(t);
int nowpos = 0;
int i;
for(i=0;i<sl;i++)
{
if(t[nowpos]==s[i])
{
pos[nowpos]=i;
nowpos++;
if(nowpos == tl) break;
}
}
int re = sl - i - 1;
nowpos = tl-1;
for(i=sl-1;i>0;i--)
{
if(t[nowpos]==s[i])
{
nowpos--;
re = max(re,i-pos[nowpos]-1);
//cout << pos[nowpos] << "*" << i << "*" << re << endl;
if(nowpos == -1) break;
}
}
re = max(re,i);
printf("%d\n",re);
return 0;
}
E. Boxers
思路:每个元素最多可变化1,求集合最大互异元素数量,于是排序,之后枚举3种情况统计即可
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5;
int a[maxn];
int main()
{
int n;
scanf("%d",&n);
int sum = 0;
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
sort(a,a+n);
int pos = 0;
for(int i=0;i<n;i++)
{
if(a[i]-1>pos)
{
sum++;
pos = a[i]-1;
}
else if(a[i]>pos)
{
sum++;
pos = a[i];
}
else if(a[i]+1>pos)
{
sum++;
pos = a[i]+1;
}
}
printf("%d\n",sum);
return 0;
}