复活小结—水题三连
宣布复活有一段时间了,CSP一轮都过去了,学了软件工程,借着C语言课的机会写了好多水题,现在恢复到普及水平了吧。。。
写几道水题题解,做个记录
NO.1 宝石串(前缀和)
https://www.luogu.org/problem/P2697
题目大意:给定一个由‘G’‘R’组成的字符串,求一段最长的区间,是‘G’‘R’数量相等
数据范围:字符串长度<=1000000
解法:‘G’视为-1,‘R’视为1,求前缀和,前缀和相同的两个位置之间的字符串符合要求,用记录各前缀和位置的方法能线性求最大值
#include<cstdio> #include<cstring> char s[1000005]; int ans,a[1000005],sl[2000005][2]; int max(int x,int y) { return x>y?x:y; } int main() { scanf("%s",s); int len=strlen(s); if(s[0]=='R') a[0]=1; else a[0]=-1; for(int i=1;i<len;i++) { if(s[i]=='R') a[i]=a[i-1]+1; else a[i]=a[i-1]-1; if(a[i]==0) ans=i+1; } for(int i=0;i<len;i++) { int w=a[i]+len; if(sl[w][0]==0) sl[w][0]=i+1; else sl[w][1]=i+1; } int m=2*len+1; for(int i=0;i<=m;i++) { ans=max(ans,sl[i][1]-sl[i][0]); } printf("%d",ans); return 0; }
NO.2
[USACO18FEB]Rest Stops(排序+贪心)
https://www.luogu.org/problem/P4266
题目大意:给出路的长度L,休息站的个数,以及john和bessie走一米需要的秒数
给出休息站的位置和停留一秒获得的美味值。Bessie可以再休息站停留。每停留一秒就能得到这个站的美味值,但是Bessie必须一直在John前面
数据范围:n<=100000,走一米需要的秒数<=100000(结果可能爆int)
解法:按照每个站的美味值排序,让Bessie在美味值最高的休息站上尽可能多地停留,直到John追上来,然后在剩下的休息站里再选择美味值最大的。
#include<cstdio> #include<algorithm> using namespace std; void read(int &y) { y=0;char x=getchar(); while(x<'0'||x>'9') x=getchar(); while(x>='0'&&x<='9') { y=y*10+x-'0'; x=getchar(); } } struct pos { int x,v; }a[100005]; bool cmp(pos x,pos y) { if(x.v>y.v) return 1; if(x.v==y.v&&x.x<y.x) return 1; return 0; } int l,n,rf,rb,tx; long long tans,ans; int main() { // freopen("testdata.in","r",stdin); read(l);read(n);read(rf);read(rb); for(int i=0;i<n;i++) { read(a[i].x);read(a[i].v); } sort(a,a+n,cmp); // for(int i=0;i<n;i++) printf("%d %d\n",a[i].x,a[i].v); for(int i=0;i<n;i++) { if(a[i].x>tx) { tans=(a[i].x-tx); tans*=(rf-rb); ans+=tans*a[i].v; tx=a[i].x; } } printf("%lld",ans); return 0; }
NO.3 细胞分裂
https://www.luogu.org/problem/P1069
题目大意:给出n个数s[i],和m1,m2
求最小的x,使pow(s[i],x)能整除pow(m1,m2)
数据范围:1≤N≤10000,1≤m1≤30000,1≤m2≤10000,1≤si≤2,000,000,000
解法:将m1因数分解,并把每个因数的数量乘m2
然后将每个si因数分解,如果存在m1有,但si没有的因数,那么这个si就不能满足要求
否则这个si的对应的x满足si,每个因数乘x之后,每个因数的数量大于m1
最终答案为所有满足题意的x中最小的一个
#include<cstdio> #include<cstring> using namespace std; void read(int &y) { y=0;char x=getchar(); while(x<'0'||x>'9') x=getchar(); while(x>='0'&&x<='9') { y=y*10+x-'0'; x=getchar(); } } int n,m1,m2,tx,ans=2147483647,maxi; int a[30005],b[30005]; int min(int x,int y) { return x<y?x:y; } int max(int x,int y) { return x>y?x:y; } int main() { // freopen("testdata1.txt","r",stdin); read(n); read(m1);read(m2); for(int i=2;i<=m1;i++) { while(m1%i==0) { m1/=i; a[i]++; } a[i]*=m2; if(a[i]) maxi=i; } // for(int i=1;i<=maxi;i++) printf("%d %d\n",i,a[i]); // return 0; for(int i=1;i<=n;i++) { read(tx); int tans=0; memset(b,0,sizeof(b)); for(int j=2;j<=tx;j++) { while(tx%j==0) { tx/=j; b[j]++; } if(j>maxi) break; } for(int j=2;j<=maxi;j++) { if(a[j]&&b[j]) { if(a[j]%b[j]==0) tans=max(tans,a[j]/b[j]); else tans=max(tans,a[j]/b[j]+1); } if(a[j]&&b[j]==0) { tans=2147483647; break; } } ans=min(tans,ans); } if(ans==2147483647) printf("-1"); else printf("%d",ans); return 0; }