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 }
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 }
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 }
手不太稳,上界有时会写错,最近需要多找找手感。
K题通过人数较多,题目比较长,队友不在,没有写。然后E和I没有看,之后看一下,不会就偷瞄大佬题解QAQ。