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


    A.Peak

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4024

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

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

    B.King of Karaoke

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4025

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

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

    J.CONTINUE...?

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4033

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

    分析:水题。当下标之和是奇数的时候,显然输出-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/showProblem.do?problemCode=4035

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

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

    M:Lucky 7

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4036

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

    分析:签到题,直接判断

    D:Sequence Swapping

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4027

    题意:给你一个长度为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/showProblem.do?problemCode=4029

    题意:题意很简单,就是给了你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。

  • 相关阅读:
    JavaEE开发中系列总结
    equals及==问题
    eclipse debug弹出窗
    MacOS Sierra 显示隐藏文件命令
    了解点Excel VBA 代码,让工作效率提升多倍~
    PADS Layout进行eco对比更新
    PCB走线规则与一些技巧介绍
    旁路电容与去耦电容的区别
    Flash download failed-Cortex-M3的原因及解决办法
    Keil U5不能识别DAP仿真器的解决办法及原因
  • 原文地址:https://www.cnblogs.com/ls961006/p/8972555.html
Copyright © 2020-2023  润新知