Codeforces Round #452 (Div. 2)
A. Splitting in Teams
水题贪心,数列有1,2两种元素,求组成3的最大方案,首先找到1的个数a,2的个数b,尽可能满足2,若b>=a,则就输出a,否则,输出b+(a-b)/3
代码如下:
#include <iostream> #include <stdio.h> #include <string.h> using namespace std; int main() { int n; int a=0,b=0,x; scanf("%d",&n); for(int i=0;i<n;i++) { scanf("%d",&x); if(x==1) a++; else b++; } if(a<=b) printf("%d\n",a); else printf("%d\n",b+(a-b)/3); return 0; }
B. Months and Years
暴力,特别注意:相邻两年不可能都是润年,因为数据量很小可以直接暴力
优化思路:看见大佬将三年的每月的天数转化成字符,(28 or 29 ---> 'a', 30 ---->'b',31---->'c') 先进行特判,然后跑一边kmp
代码如下:
#include <iostream> #include <stdio.h> using namespace std; int month[]={31,28,31,30,31,30,31,31,30,31,30,31,31,28,31,30,31,30,31,31,30,31,30,31,31,28,31,30,31,30,31,31,30,31,30,31}; int main() { int n; int a[25],b=0; scanf("%d",&n); for(int i=0;i<n;i++) { scanf("%d",&a[i]); if(a[i]/10==2&&a[i]%10==9) b++; } if(b>=2) { puts("NO"); return 0; } int flag=0; for(int j=0;j<3*12;j++) { int o=j,i; for(i=0;i<n&&o<3*12;i++) { if(month[o]==a[i]||(month[o]/10==a[i]/10&&a[i]/10==2)) o++; else break; } if(i==n) { puts("YES"); return 0; } } puts("NO"); return 0; }
代码如下:
#include<iostream> #include<stdio.h> #include<string.h> using namespace std; int next[37]; void get_next(int next[],char s[],int len) { int i=0,j=-1; j=next[0]=-1; while(i<len) { if(j==-1||s[i]==s[j]) { i++,j++; next[i]=j; } else j=next[j]; } } int kmp(char s[],char t[],int ls,int lt) { int i=0,j=0; while(i<ls) { if(j==-1 || s[i]==t[j]) i++,j++; else j=next[j]; if(j>=lt) return 1; } return 0; } int main() { int n,b=0,x,k=0; char str[]="cacbcbccbcbccacbcbccbcbccacbcbccbcbc",st[36]; scanf("%d",&n); while(n--) { scanf("%d",&x); if(x==29) b++; if(x/10==2) st[k++]='a'; else if(x==30) st[k++]='b'; else st[k++]='c'; } st[k]='\0'; if(b>=2) { puts("NO"); return 0; } get_next(next,st,strlen(st)); if(kmp(str,st,strlen(str),strlen(st))) puts("YES"); else puts("NO"); return 0; }
C. Dividing the numbers
利用等差数列的一个性质:从等差数列的定义、通项公式,前n项和公式还可推出:a(1)+a(n)=a(2)+a(n-1)=a(3)+a(n-2)=…=a(k)+a(n-k+1),(类似:p(1)+p(n)=p(2)+p(n-1)=p(3)+p(n-2)=。。。=p(k)+p(n-k+1)),k∈{1,2,…,n}。
然后,找到规律:若该数n是4的倍数,相差最小为0,选出最前面和最后面的数个n/4个,若是2的倍数,相差最小为1,与选4类似,但最后的数只选后n/4-1个元素,若该数n为奇数,将1拿出来,判断(该数-1)是否是4 ,2 的倍数,与前偶数的类似
代码如下:
#include <iostream> #include <stdio.h> using namespace std; int main() { int n; scanf("%d",&n); if(n%4==0) { printf("0\n%d ",n/2); for(int i=1;i<=n/4;i++) { if(i==n/4) printf("%d %d\n",i,n-i+1); else printf("%d %d ",i,n-i+1); } return 0; } if(n%2==0) { printf("1\n%d ",n/2); for(int i=1;i<=n/2;i+=2) { if(i==n/2) printf("%d\n",i); else printf("%d %d ",i,n-i+1); } } else { if((n-1)%4==0) { printf("1\n%d 1 ",n/2+1); for(int i=1;i<=(n-1)/4;i++) { if(i==(n-1)/4) printf("%d %d\n",i+1,n-i+1); else printf("%d %d ",i+1,n-i+1); } } else if((n-1)%2==0) { printf("0\n%d 1 ",n/2+1); for(int i=2;i<=n/2+1;i=i+2) { if(i==n/2+1) printf("%d\n",i); else printf("%d %d ",i,n-i+2); } } } return 0; }