ACM 竞赛高校联盟 练习赛 第一场

比赛链接:https://www.jisuanke.com/contest/823

A. 图像压缩四叉树

按题意构造一下树,然后按2,3,0,1的顺序遍历孩子就可以了。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 const int maxn=1e4+5;
 6 int n,order[4]={2,3,0,1};
 7 char a[maxn],ans[maxn];
 8 int idx;
 9 struct node{
10     char c;
11     node *son[4];
12     node(char c){
13         this->c=c;
14         for(int i=0;i<4;i++)
15             son[i]=NULL;
16     }
17 };
18 void build(node *s){
19     if(s->c!='x')return;
20     for(int i=0;i<4;i++){
21         s->son[i]=new node(a[++idx]);
22         if(s->son[i]->c=='x'){
23             build(s->son[i]);
24         }
25     }
26 }
27 void read(node *s){
28     if(s->c!='x')return;
29     for(int i=0;i<4;i++){
30         ans[++idx]=s->son[order[i]]->c;
31         if(s->son[order[i]])
32             read(s->son[order[i]]);
33     }
34 }
35 int main(){
36     //freopen("e:\\in.txt","r",stdin);
37     int t,kase=0;
38     scanf("%d",&t);
39     while(t--){
40         scanf("%s",a);
41         int len=strlen(a);
42         node *root=new node(a[0]);
43         ans[0]=a[0];
44         idx=0;
45         build(root);
46         idx=0;
47         read(root);
48         ans[len]='\0';
49         printf("Case #%d:\n",++kase);
50         printf("%s\n",ans);
51     }
52     return 0;
53 }
View Code

 

B. 最大子串奇数和

显然dp。。分一下奇偶,记dp[i][0]为包含第i个的子串和为偶数的最大值,dp[i][1]为奇数的,可以得到a[i]为偶数时,dp[i][0]=max(dp[i-1][0],0)+a,dp[i][1]=dp[i-1][1]+a,为奇数时同理。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 typedef long long ll;
 6 const int maxn=1e6+5;
 7 const ll INF=1e18;
 8 int n;
 9 ll dp[maxn][2];
10 int main(){
11     //freopen("e:\\in.txt","r",stdin);
12     int t,kase=0;
13     scanf("%d",&t);
14     while(t--){
15         int a;
16         dp[0][1]=dp[0][0]=-INF;
17         scanf("%d",&n);
18         scanf("%d",&a);
19         if(a%2==0){
20             dp[0][0]=a;
21         }else{
22             dp[0][1]=a;
23         }
24         for(int i=1;i<n;i++){
25             scanf("%d",&a);
26             if(a%2==0){
27                 dp[i][0]=max(dp[i-1][0],(ll)0)+a;
28                 dp[i][1]=dp[i-1][1]+a;
29             }else{
30                 dp[i][0]=dp[i-1][1]+a;
31                 dp[i][1]=max(dp[i-1][0],(ll)0)+a;
32             }
33         }
34         ll ans=dp[0][1];
35         for(int i=1;i<n;i++)
36             ans=max(ans,dp[i][1]);
37         printf("Case #%d:\n%lld\n",++kase,ans);
38     }
39     return 0;
40 }
View Code

 

C. Destroy City

贪心+抽屉原理,首先找到一个n=6时答案为1的例子,再加一个点,发现至少有两个点会被破坏,贪心一下,把新加的点放在和它一起被破坏的点上,然后以此类推,可以得到答案为⌊n/6⌋+1。

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 using namespace std;
 5 typedef long long ll;
 6 int main(){
 7     int t,kase=0;
 8     ll n;
 9     scanf("%d",&t);
10     while(t--){
11         scanf("%lld",&n);
12         printf("%lld\n",(n-1)/6+1);
13     }
14     return 0;
15 }
View Code

 

D. n点共圆

枚举可能的正k边形,k必然是n的因子,进一步考虑,k只需要是n的质因子,最多不超过6个这样的k,再枚举一下起点在[0,n/k-1]的情况,检查一下是否合法即可。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<vector>
 5 using namespace std;
 6 const int maxn=3e5+5;
 7 vector<int>v;
 8 int n,a[maxn];
 9 int pri[maxn],len=0;
10 void CalPri(){
11     bool Is_pri[maxn];
12     memset(Is_pri,-1,sizeof(Is_pri));
13     for(int i=2;i<maxn;i++){
14         if(Is_pri[i])
15             pri[len++]=i;
16         for(int j=0;j<len&&i*pri[j]<maxn;j++){
17             Is_pri[i*pri[j]]=false;
18             if(i%pri[j]==0)break;
19         }
20     }
21 }
22 int main(){
23     //freopen("e:\\in.txt","r",stdin);
24     CalPri();
25     pri[0]=3;
26     pri[1]=4;
27     int t,kase=0;
28     scanf("%d",&t);
29     while(t--){
30         bool ans=false;
31         scanf("%d",&n);
32         v.clear();
33         for(int i=0;i<n;i++)scanf("%d",&a[i]);
34         for(int i=0;i<len&&pri[i]<=n;i++){
35             if(n%pri[i]==0)v.push_back(pri[i]);
36         }
37         for(int i=0;i<v.size();i++){
38             int &k=v[i],step=n/k;
39             for(int s=0;s<step;s++){
40                 bool ok=true;
41                 for(int j=s;j<n;j+=step){
42                     if(a[j]==0){ok=false;break;}
43                 }
44                 if(ok){ans=true;break;}
45             }
46             if(ans)break;
47         }
48         if(ans)printf("Case #%d: Yes\n",++kase);
49         else printf("Case #%d: No\n",++kase);
50     }
51     return 0;
52 }
View Code

 

posted @ 2017-07-30 16:48  7391_KID  阅读(404)  评论(0编辑  收藏  举报