A. Circle of Students
题意:给你一个长度为n的序列(成环),问该序列是否满足从某一位置开始顺时针或逆时针走是有序递增的
思路:找到1的下标,分别判从1的位置开始顺时针走或逆时针走,能否走到n
#include<bits/stdc++.h>
using namespace std;
#define inc(i,x,n) for(register int i=x;i<=n;++i)
#define dec(i,x,n) for(register int i=x;i>=n;--i)
typedef pair<int,int> P;
const int N=2e2+5;
int A[N];
int clockwise(int pos,int n){
for(int i=pos;i<n+pos-1;i+=1){
if(A[i%n]+1!=A[(i+1)%n]) return 0;
}
return 1;
}
int counterclockwise(int pos,int n){
for(int i=pos;i>pos-n+1;--i){
if(A[(i+n)%n]+1!=A[(i-1+n)%n]) return 0;
}
return 1;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
int n;
scanf("%d",&n);
int pos;
inc(i,0,n-1){
scanf("%d",&A[i]);
if(A[i]==1) pos=i;
}
if(clockwise(pos,n)||counterclockwise(pos,n))
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
B. Equal Rectangles
题意:给你4n根木棍,长度不一定相同,问能否用这4n根木根构成n个矩形
思路:因为木棍的长度在[1,10000]之间,所以先统计每种长度木棍的个数,那么每种长度的木棍能参与构成的矩形个数是a[i]/2个,之后一一枚举不同面积矩形能组成的个数,若其中存在一种矩形能构成的个数>=n,那么有解
#include<bits/stdc++.h>
using namespace std;
#define inc(i,x,n) for(register int i=x;i<=n;++i)
#define dec(i,x,n) for(register int i=x;i>=n;--i)
typedef pair<int, int> P;
const int N = 1e4 + 5;
int a[N];
int main() {
int T;
scanf("%d", &T);
while(T--) {
int n;
scanf("%d", &n);
memset(a, 0, sizeof(a));
inc(i, 1, 4 * n) {
int x;
scanf("%d", &x);
a[x] += 1;
}
vector<int> v;
inc(i, 1, 10000) {
if(a[i] >= 2)
v.push_back(i);
a[i] /= 2;
}
map<int, int> M;
for(int i = 0; i < v.size(); i += 1) {
if(a[v[i]] > 1)
M[v[i]*v[i]] += a[v[i]] / 2;
for(int j = i + 1; j < v.size(); j += 1) {
M[v[i]*v[j]] += min(a[v[i]], a[v[j]]);
}
}
map<int, int>::iterator it;
int sign = 0;
for(it = M.begin(); it != M.end(); it++) {
if(it->second >= n) {
sign = 1;
break;
}
}
if(sign)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
C. Common Divisors
题意:给你一个长度为n的序列,问存在多少个数能被整个序列里的元素整除
思路:求出n个数的最大公约数,最大公约数的约数个数就是答案
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N = 4e5 + 5;
const int Mod = 1e9 + 7;
inline int read();
inline void write(int x);
long long a[N];
int main() {
int n;
scanf("%d", &n);
long long gcd;
for(int i = 1; i <= n; i += 1) {
scanf("%lld", &a[i]);
if(i == 1)
gcd = a[i];
else
gcd = __gcd(gcd, a[i]);
}
vector<int> v;
for(long long i = 2; i * i <= gcd; i += 1) {
if(gcd % i == 0) {
int c = 0;
while(gcd % i == 0) {
c += 1;
gcd /= i;
}
v.push_back(c);
}
}
if(gcd > 1)
v.push_back(1);
long long res = 1;
for(int x : v)
res *= (long long)(x + 1);
printf("%lld\n", res);
return 0;
}
inline int read() {
int x = 0, f = 1;
char c = getchar();
for(; !isdigit(c); c = getchar())
if(c == '-')
f = -1;
for(; isdigit(c); c = getchar())
x = x * 10 + c - '0';
return x * f;
}
inline void write(int x) {
if(x >= 10)
write(x / 10);
putchar(x % 10 + '0');
}
D.Remove the Substring
题意:给你两个字符串x,y,希望你删掉x串中长度最长的一个子串,使得x串中仍包含y这个子序列
思路:可删除的最长子串存在的地方只有三种情况,1.x串首部 2.x串尾部 3.x串中间
我们可以这样,先预处理出y串中每个字符在x串中最后出现的位置,记录下标。然后我们从头开始遍历x串,对于y[pos]和y[pos-1],我们肯定是要找在x串中间距尽量大且合法的y[pos]和y[pos-1]的位置,它们之间的字符串长度就是我们要删去的长度
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 2e5 + 5;
char x[N], y[N];
int last[N], pos, res;
int main() {
scanf("%s %s", x, y);
int xi = strlen(x);
int yi = strlen(y);
pos = xi;
for(int i = yi - 1; i >= 0; --i) {
--pos;
while(x[pos] != y[i])
--pos;
last[i] = pos;
}
res = pos = 0;
for(int l = 0; l < xi; l += 1) {
if(pos >= yi) {
res = max(res, xi - l);
break;
}
int r = last[pos] - 1;
res = max(res, r - l + 1);
if(y[pos] == x[l])
pos += 1;
}
printf("%d\n", res);
return 0;
}
E. Boxers
题意:给你一个长度为n的序列,序列中每个数可以+1或-1一次,让你对这个序列进行操作,使最后序列中数互异的个数最多
思路:贪心每一步
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=2e5+5;
int a[N],res;
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;i+=1) scanf("%d",&a[i]);
sort(a+1,a+1+n);
for(int i=1;i<=n;i+=1)
{
if(i==1){
if(a[i]>1) --a[i];
}
else if(i==n)
a[i]+=1;
else
{
if(a[i]!=a[i-1]){
if(a[i]-a[i-1]>1) --a[i];
else if(a[i]+1==a[i-1]) a[i]+=1;
}
else a[i]+=1;
}
if(a[i]!=a[i-1]) res+=1;
}
printf("%d\n",res);
return 0;
}