五一题单
五一题单:https://vjudge.net/contest/436484#problem
1.https://vjudge.net/contest/436484#problem/J
J题wa了好多发,思路挺简单,就是很多细节需要注意。
题意:给定字符串中第一个“ * ”和最后一个都要变成“ x ”,然后给定一个数字k,最多隔k个数要有一个x。
思路:从前从后分别遍历一次,找到第一个*和最后一个*变成x,然后从第一个*开始遍历,每隔k个字符就需要有一个x,注意x只能由*改变而来,因此记录下x的位置下一个的k个判断就从记录的这里开始了,直接两个循环就行,注意数据范围,j的值是不能大于n的。
代码:
#include<stdio.h> #include<string.h> int main() { int t,n,k; char str[105]; scanf("%d",&t); while(t--){ int cnt=0; int fg1,fg2; scanf("%d %d",&n,&k); getchar(); gets(str); for(int i=0;i<n;i++){ if(str[i]=='*'){ str[i]='x'; cnt++; fg1=i; break; } } for(int i=n-1;i>=0;i--){ if(str[i]=='*'){ str[i]='x'; cnt++; break; } } for(int i=fg1;i<n;i++){ if(str[i]=='x'){ int fg=0; for(int j=i+k;j>i&&j<n;j--){ if(str[j]=='x'){ i=j-1; fg=1; break; } } if(fg==0){ for(int j=i+k;j>i&&j<n;j--){ if(str[j]=='*'){ i=j-1; str[j]='x'; cnt++; break; } } } } } printf("%d\n",cnt); } return 0; }
2.https://vjudge.net/contest/436484#problem/C
C题主要也是理解题意,理清思路(刚开始没有想到的时候感觉还是有点懵)。
题意:在一个数组里面,如果gcd(a,b)的结果为数组里的最小值就可以交换a和b的位置,如果能形成升序输出yes否则no。
思路:需要是gcd(a,b)结果为数组最小值,那么a或者b就是数组最小值,假设a是最小值,那么为了使gcd(a,b)=a,就需要b是a的倍数。
我们可以把所给数组sort排个序看成一个新的数组,将这个数组与原数组对比,如果有元素是不一样的,就判断是否是通过交换而来的,如果是通过交换得来的,就yes,否则no。
代码:
#include<bits/stdc++.h> using namespace std; int main() { int t,n; int a[100005],b[100005]; scanf("%d",&t); while(t--){ int fg=0,x=1e9; memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%d",&a[i]); b[i]=a[i]; x=min(x,a[i]); } sort(b,b+n); for(int j=0;j<n;j++){ if(a[j]!=b[j]&&a[j]%x!=0){ printf("NO\n"); fg=1; break; } } if(fg==0) printf("YES\n"); } return 0; }
3.https://vjudge.net/contest/436484#problem/E
题意:给出一个数组,让你将其分为n个一组,共k组,使每一组的中位数的和最大。(向上取中位数)
思路:从后往前隔k个取数尽量要大。
代码:
#include<stdio.h> #include<string.h> long long a[1000005]; int main() { long long t,n,k,m; scanf("%lld",&t); while(t--){ long long fg1,fg2,sum=0; scanf("%lld %lld",&n,&k); m=n*k; for(long long i=1;i<=m;i++){ scanf("%lld",&a[i]); } fg1=n/2+1; fg2=m-fg1; for(long long j=fg2+1;k;j-=fg1,k--) sum+=a[j]; printf("%lld\n",sum); } return 0; }
4.https://vjudge.net/contest/436484#problem/D
D题题意:给出一个字符串,其中只有0和1两种数字,数字分别有其价格,可以将0变为1,1变为0,变化有一定价格,最后将所有的数字都买了求最小需要多少价格。
思路:比较简单,当变化的价格比0和1的差值大的时候就亏了,所以不变,当变化价格小于1和0的差值时,最后只有一种数字,加上变化的价格就是最终的总价格。
代码:
#include<bits/stdc++.h> using namespace std; int main() { int t,n,a,b,c; int c0,c1,h; char str[1005]; scanf("%d",&t); while(t--){ int fg1=0,fg2=0; scanf("%d %d %d %d",&n,&c0,&c1,&h); getchar(); gets(str); for(int i=0;i<n;i++){ if(str[i]=='0') fg1++; else fg2++; } a=c0-c1; if(a<0) a=-a; if(a<=h) printf("%d\n",fg1*c0+fg2*c1); else{ if(c0>c1) printf("%d\n",c1*n+fg1*h); else printf("%d\n",c0*n+fg2*h); } } return 0; }
5.https://vjudge.net/contest/436484#problem/F
题意&思路(好好学英语):一个数组有n个数字,每个数字转换成二进制有k位,并且每个数按位与后为0且和最大。按位与为0的话就需要每一位都得有至少一个0(按位与为0的情况:1,0;0,1;0,0)。因为要保证最大所以只有一个0就够了,最后求得有多少个这样的数组。又因为n^k太大了要用快速幂处理一下。(注意有long long)
快速幂部分代码:
while(k){ if(k&1){ ans = (ans*n)%N; } n = (n*n)%N; k>>=1; }
all:
#include<stdio.h> int main() { long long t,n,k,cnt; scanf("%lld",&t); int x=1e9+7; while(t--){ cnt=1; scanf("%lld %lld",&n,&k); while(k){ if(k&1){ cnt=cnt*n%x; } n=n*n%x; k>>=1; } printf("%lld\n",cnt); } return 0; }
to be continued......