https://ac.nowcoder.com/acm/contest/5758
B:减成一
分析:
1.如果前面那个数比这个数大,那直接跳过,因为前面一个数可以带它躺成1。
2.如果前面那个数比这个数小,那区间是只能扩到前一个数这么大,因此还要进行多余的操作使自己变成1,于是产生了(a[i]-a[i-1])代价。
代码:
#include "bits/stdc++.h" using namespace std ; typedef long long ll; ll t,n,sum; ll a[100005]; int main(){ cin>>t; while(t--){ cin>>n; for(int i=1;i<=n;i++) { cin>>a[i]; a[i]=a[i]-1; } sum=0; for(int i=1;i<=n;i++) { if(a[i]>=a[i-1]){ sum+=a[i]-a[i-1]; } } cout<<sum<<endl; } return 0; }
c:面积
分析:
面积=正方形的面积x^2+两个圆面积23.14(a/2)^2
代码:
#include<stdio.h> #include<algorithm> #include<string.h> #include<math.h> #include<set> using namespace std; typedef long long ll; int i,j,cnt,n,k,t,b,m,ans; using namespace std; int main() { scanf("%d",&t); while(t--){ double x; scanf("%lf",&x); double r=x/2; printf("%.2lf\n",3.14*r*r*2+x*x); } }
E:赛马
分析:
田忌赛马改编题,直接贪心即可。
如此贪心:
从我方大的马和敌方大的马开始比,如果我方的马大于敌方,则贡献值+1,换到对方下一匹马,换到我放下一匹马。
如果我方最大的马都输了,则换到对方下一匹马,我方不变。
大体上懂得取舍便可以了,详细分析可以百度田忌赛马贪心了解。
代码:
#include<iostream> #include<algorithm> #include<string.h> using namespace std; bool ran(int x,int y) { return x<y; } int tj[1001],king[1001]; int main() { int k,i,j,t; scanf("%d",&t); while(t--) { scanf("%d",&k); if(k==0) continue; memset(tj,0,sizeof(tj)); memset(king,0,sizeof(king)); for(i=0;i<k;i++) cin>>tj[i]; for(i=0;i<k;i++) cin>>king[i]; sort(tj,tj+k,ran); sort(king,king+k,ran); long int count=0; int tj_min=0,tj_max=k-1; int king_min=0,king_max=k-1; while(tj_min<=tj_max) { if(tj[tj_max]>king[king_max]) { count++; tj_max--;king_max--; } else if(tj[tj_min]>king[king_min]) { count++; tj_min++;king_min++; } else { // if(tj[tj_min]<king[king_max]) // count--; tj_min++;king_max--; } } cout<<count<<endl; } return 0; }
F:三角形
分析:
三角形两边之和大于第三边,为了使得切割段数最多,我们由切割为1的片段开始,一开始为1,下个为1,再下个不能取1了,因为会组成三角形,所以我们取敲好不能组成三角形的最小片段2,然后2也不能取了,因为221会组成三角形,进而取3,于是我们发现每次取得的数恰好等于前面两个数的和,由此使得其恰好不能构成三角形,而112358这些数我们不难看出是斐波那契数列,由于斐波那契增长很快,从1开始枚举到总长度即可,记得开unsigned long long.
代码:
#include<iostream> #include<string.h> #include<stdio.h> #include<algorithm> using namespace std; typedef unsigned long long ll; ll a[105]; int main(){ int T; cin>>T; a[1]=1,a[2]=1; for(int i=3;i<=100;i++) a[i]=a[i-1]+a[i-2]; while(T--){ ll n; cin>>n; ll res=0; for(int i=1;i<=100;i++){ if(a[i]>n) break; else n-=a[i],res++; } cout<<res<<endl; } return 0; }
H:直线
分析:
结论题,答案为n*(n-1)/2
最优方案每条线都与其他的线相交,则每条线的贡献值为n-1,总共有n条线,同一根线算了两次。
数据范围要用大数,最好写个python,当然套用大数板子还是蛮舒服的。
代码:
#include "bits/stdc++.h" using namespace std ; typedef long long ll; void reverse(char * c) { int len = strlen(c); for(int i=0; i<len/2; i++) swap(c[i],c[len-i-1]); } void multiplication(char * srca,char * srcb,char * dest)//未翻转 { int ia,ib,c, na = strlen(srca), nb = strlen(srcb); reverse(srca); reverse(srcb); for(ia=0; ia<na; ia++) { c = 0; for(ib=0; ib<nb; ib++) { int t = (srca[ia]-48) * (srcb[ib]-48) + c,tt; if(dest[ia+ib]>47) tt = dest[ia+ib]-48 + t; else tt = t; dest[ia+ib] = tt%10 +48; c = tt/10; }// for while(c) //处理进位,直到进位为0 { int t; if(dest[ia+ib]>47) t = dest[ia+ib] - 48 + c; else t = c; dest[ia+ib++] = t%10 + 48; c /= 10; }// while }// for //将两个乘数和乘积都改为大端法 reverse(dest); reverse(srca); reverse(srcb); } void division(char * src,int n,char * dest) { int len = strlen(src), i, //计数 k, //商的下标 t = 0, //新的余数 s = 0; //余数 bool flag = true; //商是否有了第一个有效位,防止商首部一直出现0 for(i=0,k=0; i<len; i++) { t = s*10+(src[i]-48); //新余数 if(t/n>0 || t==0) //余数为0要修改商 dest[k++] = t/n+48,s = t%n,flag = false; else //不够除,修改余数 { s = t; if(!flag) //商已经有有效位了,补零 dest[k++] = '0'; }// if }// for //::memset(src,0,len); //memcpy(src,dest,strlen(dest)); } char a[100],b[100],c[100],temp[100],ans[100]; int main() { int t; scanf("%d",&t); while(t--){ memset(a,'\0',sizeof(a)); memset(b,'\0',sizeof(b)); memset(c,'\0',sizeof(c)); memset(temp,'\0',sizeof(temp)); memset(ans,'\0',sizeof(ans)); long long n,m; scanf("%lld",&n); m=n-1; sprintf(a, "%lld", n); sprintf(b, "%lld", m); multiplication(a,b,c); division(c,2,ans); printf("%s",ans); printf("\n"); } }
python:
n=int(input()) i=0 while i < n: a=int(input()) print (int(a*(a-1)//2)) i=i+1
J:最大值
分析:
正解好像是kmp,但是不会,看了大佬题解我才知道可以用二分蛮过去。
截取字符串0-len,再用非前缀长度为len的字符串与它比较,如果相等就是表示len这个长度可以做到,不相等判断下一个,如此进行二分选择,如果到最后还没有相等的,就是len不行。
代码:
#include "bits/stdc++.h" using namespace std ; typedef long long ll; string s; ll n,T; int check(int len){ string tmp=s.substr(0,len); for(int i=1;i+len<=n;i++){ string q=s.substr(i,len); if(q==tmp) return 1; } return 0; } int main(){ cin>>T; while(T--){ cin>>s; n=s.size(); int l=0,r=n,res; while(l<=r){//二分 int mid=(l+r)>>1; if(check(mid)){ res=mid; l=mid+1; } else r=mid-1; } cout<<res<<endl; } return 0; }