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 }
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 }
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 }
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 }