The 15th Zhejiang Provincial Collegiate Programming Contest 训练报告

A.Peak

题目链接:http://acm.zju.edu.cn/onlinejudge/showContestProblem.do?problemId=5752

题意:给你一个数字序列,问你该序列是不是先严格递增然后再严格递减,是的话输出Yes,不是输出No。

分析:签到题,直接判断是否先增再减即可。

B.King of Karaoke

题目链接:http://acm.zju.edu.cn/onlinejudge/showContestProblem.do?problemId=5753

题意:给你两个序列,长度相等,然后你可以给第一个序列整体加上或者减去同一个数字,使得他和第二个序列对应位置相同的元素达到最多,输出最多是多少

分析:签到题,直接输出对应位置每个差值出现的次数,输出最大次数即可。

J.CONTINUE...?

题目链接:http://acm.zju.edu.cn/onlinejudge/showContestProblem.do?problemId=5759

题意:输入t,代表测试组数,每次给你一个n,给你一个只包含0和1的长度为n的字符串。现在要你把0和1分到1、2、3、4这四个组中,要求0只能分到第1组或者第2组,1只能分到第3组或者第4组,且第1组和第3组的数字下标之和等于第二组和第四组的下标之和。(下标从1开始)不存在输出-1。

扫描二维码关注公众号,回复: 91834 查看本文章

分析:水题。当下标之和是奇数的时候,显然输出-1。接下来我们就可以把1和3组看成A组,2和4组看成B组。当n为偶数时,我们可以把第1个和第n个绑在一起,第2个和第n-1个绑在一起,这样就可以绑成偶数组,然后平均分到A和B组中就可以了。如果n为奇数,我们把第n个单独成1组,然后剩下的n-1个按偶数处理。这样分到A组的0标1,1标3,分到B组的0标2,1标4就可以了。

AC代码:(写的比较丑)

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 int ans1,ans2;
 6 int id[1000005];
 7 int main() {
 8     ios_base::sync_with_stdio(false);
 9     cin.tie(0);
10     int t;
11     cin>>t;
12     long long n;
13     string s;
14     while(t--){
15         cin>>n;
16         cin>>s;
17         long long sum=(n+1)*n/2;
18         if(sum%2==1){
19             cout<<-1<<endl;
20             continue;
21         }
22         if(n%2==1){
23             if(s[n-1]=='0'){
24                 id[n]=1;
25             }
26             else {
27                 id[n]=3;
28             }
29             for(int i=1;i<=n/2;i++){
30                 if(i%2==0){
31                     if(s[i-1]=='0'){
32                         id[i]=1;
33                     }
34                     else {
35                         id[i]=3;
36                     }
37                     if(s[n-i-1]=='0'){
38                         id[n-i]=1;
39                     }
40                     else {
41                         id[n-i]=3;
42                     }
43                 }
44                 if(i%2==1){
45                     if(s[i-1]=='0'){
46                         id[i]=2;
47                     }
48                     else {
49                         id[i]=4;
50                     }
51                     if(s[n-i-1]=='0'){
52                         id[n-i]=2;
53                     }
54                     else {
55                         id[n-i]=4;
56                     }
57                 }
58             }
59         }
60         else {
61             for(int i=1;i<=n/2;i++){
62                 if(i%2==0){
63                     if(s[i-1]=='0'){
64                         id[i]=1;
65                     }
66                     else {
67                         id[i]=3;
68                     }
69                     if(s[n-i]=='0'){
70                         id[n-i+1]=1;
71                     }
72                     else {
73                         id[n-i+1]=3;
74                     }
75                 }
76                 if(i%2==1){
77                     if(s[i-1]=='0'){
78                         id[i]=2;
79                     }
80                     else {
81                         id[i]=4;
82                     }
83                     if(s[n-i]=='0'){
84                         id[n-i+1]=2;
85                     }
86                     else {
87                         id[n-i+1]=4;
88                     }
89                 }
90             }
91         }
92         for(int i=1;i<=n;i++){
93             cout<<id[i];
94         }
95         cout<<endl;
96     }
97     return 0;
98 }
View Code

L:Doki Doki Literature Club

题目链接:http://acm.zju.edu.cn/onlinejudge/showContestProblem.do?problemId=5761

题意:给你n个字符串,然后每个字符串有一个价值vi,现在要你选m个,使得最大。然后输出最大的H,相同的价值,选字典序小的。

分析:签到题,直接按结构体排序,如果v相等,返回字典序小的,否则返回v大的,然后计算输出就可以了。

M:Lucky 7

题目链接:http://acm.zju.edu.cn/onlinejudge/showContestProblem.do?problemId=5762

题意:给你n个数字,然后给你一个b,问你是否存在(ai+b)%7==0,存在输出Yes,不存在输出No。

分析:签到题,直接判断

D:Sequence Swapping

题目链接:http://acm.zju.edu.cn/onlinejudge/showContestProblem.do?problemId=5755

题意:给你一个长度为n的字符串,只包含'('和‘)’,然后给你每个字符的价值vi。如果s[i]='('并且s[i+1]=')',那么你就可以交换他们,并且的到vi*v[i+1]的价值。交换之后这两个字符和价值均交换。然后问你最多可以得到多少价值。

分析:首先对于这个题,经过分析,可以得知,题目等价于:每一个'('交换到哪一个‘)’位置之后,得到的价值最大。即每一个'('可以选择与他之后的‘)’交换或者不交换。问你经过交换之后,得到的价值最大是多少。那么我们可以前缀和记录每一个'('交换到每一个‘)’位置得到的价值。由于左边的‘(’可以交换的位置上界受他右边的‘(’交换到的位置的影响,因此我们可以用v[i][j]来表示倒数第i个‘(’交换到倒数第j个‘)’所能得到的价值。都用倒数是因为倒数第i+1个‘(’如果交换到倒数第j个‘)’,那么截止到这一步,他可以得到的最大价值就是倒数第i个‘(’交换到倒数第j个‘)’之前的所有选择中的最大值+v[i+1][j]。那么现在就好比给你一个二维数组,从左上角到右下角,每次可以向右或者向下走,然后将所有拐点处的数字相加,求拐点之和最大的问题。这是一个经典的DP问题(会的同学就不需要看后边了),对于每一个位置v[i][j],他都可以从上一行的前j个元素中取最大,然后加上v[i][j],就是他可以的到的最大值。为了维护前j个的最大值,v[i][j]还应该等于max(v[i][j],v[i][j-1]),因此递推关系式就是:

                    v[i][j]=v[i-1][j]+v[i][j];
                    if(j!=1) v[i][j]=max(v[i][j],v[i][j-1]);

AC代码:

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 long long a[10005];
 6 long long v[1005][1005];
 7 int l,r,ID[1005],n;
 8 string s;
 9 void cal() {
10   l=0, r=0;
11   for (int i=n-1;i>=0;i--) {
12     if (s[i]==')') ID[i]=++r;
13     else {
14       ID[i]=++l;
15     }
16   }
17   for (int i=n-1;i>=0;i--) {
18     if (s[i]=='(') continue;
19     long long x=a[i+1];
20     int p=i-1;
21     while (p>=0) {
22       if (s[p]=='(') {
23         v[ID[p]][ID[i]]=a[p+1]*x;
24       }
25       else {
26         x+=a[p+1];
27       }
28       p--;
29     }
30   }
31 }
32 int main() {
33     ios_base::sync_with_stdio(false);
34     cin.tie(0);
35     int t;
36     cin>>t;
37     while(t--){
38         cin>>n;
39         cin>>s;
40         memset(v,0,sizeof(v));
41         for(int i=1;i<=n;i++){
42             cin>>a[i];
43         }
44         cal();
45         long long sum=0;
46         for(int i=1;i<=l;i++){
47             for(int j=1;j<=r;j++){
48                 v[i][j]=v[i-1][j]+v[i][j];
49                 if(j!=1) v[i][j]=max(v[i][j],v[i][j-1]);
50                 sum=max(sum,v[i][j]);
51             }
52         }
53         cout<<sum<<endl;
54     }
55     return 0;
56 }
View Code

F:Now Loading!!!

题目链接:http://acm.zju.edu.cn/onlinejudge/showContestProblem.do?problemId=5763

题意:题意很简单,就是给了你n个ai还有m个pi,然后让你带入公式,每一次可以求得一个zi,然后带入公式求得一个值,然后问你值是多少

分析:首先我们看到了第一个公式的分母,因为是log级别,所以他的取值范围在1到64之间。题目给出2<=a[i]<=1e9。也就是说对于a[i]/log我们可以直接求出所有情况下的答案,即a[i]除以1到64的所有数字。分母也只有1到64中情况,我们就可以对a数组排序,枚举pi,然后对于每一个p[j],判断哪些a[i]的分母是相同的,这里可以二分判断哪些区间内的logp[j](a[i])是相同的,我们可以就之前预处理的信息,维护前缀和,快速的求出相同分母连续的a[i]求和得到的值。然后处理一些细节,就AC了。当时没有判断p[i]^k<a[now],T了一发。

AC代码:

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 long long a[1000005],p[1000005];
 6 long long mod=1e9;
 7 long long sm[100005][100];
 8 int main()
 9 {
10     ios_base::sync_with_stdio(false);
11     cin.tie(0);
12     int t;
13     cin>>t;
14     int n,m;
15     while(t--){
16         cin>>n>>m;
17         for(int i=1;i<=n;i++){
18             cin>>a[i];
19         }
20         for(int i=1;i<=m;i++){
21             cin>>p[i];
22         }
23         sort(a+1,a+1+n);
24         for(int i=1;i<=64;i++){
25             sm[0][i]=0;
26         }
27         for(int i=1;i<=n;i++){
28             for(int j=1;j<=65;j++){
29                 sm[i][j]=sm[i-1][j]+a[i]/j;
30             }
31         }
32         long long result=0;
33         int now=0;
34         for(int i=1;i<=m;i++){
35             long long sum=0;
36             long long ans=1;
37             now=0;
38             for(int j=1;j<64;j++){
39                 ans*=p[i];
40                 if(ans<a[now+1]){
41                     continue;
42                 }
43                 int low=now,high=n;
44                 int re=now;
45                 while(low<=high){
46                     int mid=(low+high)/2;
47                     if(a[mid]<=ans){
48                         re=mid;
49                         low=mid+1;
50                     }
51                     else {
52                         high=mid-1;
53                     }
54                 }
55                // cout<<i<<" "<<j<<" "<<re<<" "<<now<<" "<<sm[re][j]<<" "<<sm[now][j]<<endl;
56                 sum=sum+sm[re][j]-sm[now][j];
57                 now=re;
58                 if(now>=n) break;
59             }
60             result=(result+sum%mod*i%mod)%mod;
61         }
62         cout<<result<<endl;
63     }
64 
65     return 0;
66 }
View Code

手不太稳,上界有时会写错,最近需要多找找手感。

K题通过人数较多,题目比较长,队友不在,没有写。然后E和I没有看,之后看一下,不会就偷瞄大佬题解QAQ。

猜你喜欢

转载自www.cnblogs.com/ls961006/p/8972555.html