杭电OJ第11页
2000.ASCII码排序
#include <stdio.h> void swab(char &a,char &b){ char t=a; a=b; b=t; } int main(){ char a,b,c; while(scanf("%c%c%c",&a,&b,&c)!=EOF){ getchar();//吃掉换行符 if(a>b) swab(a,b); if(a>c) swab(a,c); if(b>c) swab(b,c); printf("%c %c %c\n",a,b,c); } return 0; }
2001.计算两点间的距离
结果保留两位小数:处理方式先乘 100 + 0.5 强制转化成int 再除100
#include<stdio.h> #include<math.h> int main(){ float x1,y1,x2,y2; while(scanf("%f %f %f %f",&x1,&y1,&x2,&y2)!=EOF){ getchar(); float temp=(x2-x1)*(x2-x1)+(y2-y1)*(y2-y1); float t=sqrt(temp); int x=(int)(t*100+0.5); float ans=x/100.0; printf("%.2f\n",ans); } return 0; }
2002.计算球体积
不用想的太复杂,无需考虑四舍五入的问题
#define PI 3.1415927 #include<stdio.h> int main(){ double r; while(scanf("%lf",&r)!=EOF){ getchar(); double temp=4/3.0*PI*r*r*r; printf("%.3lf\n",temp); } return 0; }
2003.求绝对值
#include <stdio.h> int main(){ double a; while(scanf("%lf",&a)!=EOF){ getchar(); a=a>=0?a:-a; printf("%.2lf\n",a); } return 0; }
2004.成绩转换
#include <stdio.h> int main(){ int a; while(scanf("%d",&a)!=EOF){ getchar(); if(a>=90&&a<=100) printf("A\n"); else if(a>=80&&a<=89) printf("B\n"); else if(a>=70&&a<=79) printf("C\n"); else if(a>=60&&a<=69) printf("D\n"); else if(a>=0&&a<=59) printf("E\n"); else printf("Score is error!\n"); } return 0; }
2005.第几天?
闰年:能够被4整除但不能被100整除或者能够被400整除
#include <stdio.h> int isRunYear(int a){ if((a%4==0&&a%100!=0)||a%400==0){ return 1; } return 0; } int main(){ int a,b,c; int ans; int day[]={31,28,31,30,31,30,31,31,30,31,30,31}; while(scanf("%d/%d/%d",&a,&b,&c)!=EOF){ getchar(); ans=0; if(b==2){ ans=31; }else if(b>2){ int i; for(i=0;i<b-1;i++){ ans=ans+day[i]; } ans+=isRunYear(a); } ans=ans+c; printf("%d\n",ans); } return 0; }
2006.求奇数的乘积
#include <stdio.h> int main(){ int n; while(scanf("%d",&n)!=EOF){ int i; int ans=1; int t; for(i=0;i<n;i++){ scanf("%d",&t); if(t%2==1){ ans=ans*t; } } printf("%d\n",ans); getchar(); } return 0; }
2007.平方和和立方和
有个坑,不一定先输入小的数,后输入大的
#include <stdio.h> int main(){ long a,b; while(scanf("%ld %ld",&a,&b)!=EOF){ getchar(); if(a>b){ long t=a; a=b; b=t; } long i; long c=0; long d=0; for(i=a;i<=b;i++){ if(i%2==0){ c+=i*i; }else{ d+=i*i*i; } } printf("%ld %ld\n",c,d); } return 0; }
2008.数值统计
#include <stdio.h> int main(){ int n; scanf("%d",&n); while(n!=0){ int i; int a=0; int b=0; int c=0; double t=0; for(i=0;i<n;i++){ scanf("%lf",&t); if(t>0) c++; else if(t==0) b++; else a++; } printf("%d %d %d\n",a,b,c); scanf("%d",&n); } return 0; }
2009.求数列的和
#include <stdio.h> #include <math.h> int main(){ double n; int m; while(scanf("%lf %d",&n,&m)!=EOF){ getchar(); int i; double ans=0.0; for(i=0;i<m;i++){ ans+=n; n=sqrt(n); } printf("%.2f\n",ans); } }
2010.水仙花数
OJ对于输出的要求很高,注意输出格式,要求输出的最后一个字符后面不能有空格
#include <stdio.h> int main(){ int m,n; while(scanf("%d %d",&m,&n)!=EOF){ getchar(); int i; int flag=0; for(i=m;i<=n;i++){ int a=i/100; int b=i/10%10; int c=i%10; if((a*a*a+b*b*b+c*c*c)==i){ if(flag==1) printf(" %d",i); else printf("%d",i); flag=1; } } if(flag==0) printf("no\n"); else printf("\n"); } return 0; }
2011.多项式求和
#include <stdio.h> int main(){ int m; scanf("%d",&m); while(m>0){ int n; scanf("%d",&n); int i; int flag=1; double ans=0.0; for(i=1;i<=n;i++){ if(flag==1){ ans=ans+1.0/i; flag=0; }else if(flag==0){ ans=ans-1.0/i; flag=1; } } printf("%.2f\n",ans); m--; } return 0; }
2012.素数判定
判断n是否是素数:能否被2-n-1整除
#include <stdio.h> int isPrime(int n){ int i; for(i=2;i<n;i++){ if(n%i==0) return 0; } return 1; } int main(){ int x,y; scanf("%d %d",&x,&y); while(x!=0||y!=0){ int i; int flag=1; for(i=x;i<=y;i++){ if(isPrime(i*i+i+41)==0){ flag=0; break; } } if(flag==1) printf("OK\n"); else if(flag==0) printf("Sorry\n"); scanf("%d %d",&x,&y); } return 0; }
2013.蟠桃记
看清题目:吃掉昨天的一半多一个
#include <stdio.h> int main(){ int n; while(scanf("%d",&n)!=EOF){ int ans=1; int i; for(i=1;i<n;i++){ ans=(ans+1)*2; } printf("%d\n",ans); } }
2014.青年歌手大奖赛_评委会打分
#include <stdio.h> int main(){ int n; while(scanf("%d",&n)!=EOF){ int i; double a[n]; for(i=0;i<n;i++){ scanf("%lf",&a[i]); } int min=0; int max=0; int j; for(j=0;j<n;j++){ if(a[min]>a[j]) min=j; if(a[max]<a[j]) max=j; } a[min]=0; a[max]=0; double ans=0.0; for(j=0;j<n;j++){ ans+=a[j]; } printf("%.2f\n",ans/(n-2)); } return 0; }
2015.偶数求和
#include <stdio.h> int main(){ int n,m; while(scanf("%d %d",&n,&m)!=EOF){ if(n<=m){ printf("%d\n",(2+(n-1)*2+2)/2); }else{ int i; int count=n/m; int b=n%m; int a1=2; int a2=(m-1)*2+2; for(i=1;i<=count;i++){ if(i==1){ printf("%d",(a1+a2)/2); a1=a2+2; a2=((i+1)*m-1)*2+2; }else{ printf(" %d",(a1+a2)/2); a1=a2+2; a2=((i+1)*m-1)*2+2; } } if(b!=0){ int sum=0; for(i=0;i<b;i++){ sum+=a1; a1=a1+2; } printf(" %d\n",sum/b); }else{ printf("\n"); } } } return 0; }
2016.数据的交换输出
#include <stdio.h> int main(){ int n; scanf("%d",&n); while(n!=0){ int a[n]; int i; int min=0; for(i=0;i<n;i++){ scanf("%d",&a[i]); if(a[i]<a[min]) min=i; } int t=a[0]; a[0]=a[min]; a[min]=t; for(i=0;i<n;i++){ if(i==0) printf("%d",a[i]); else printf(" %d",a[i]); } printf("\n"); scanf("%d",&n); } return 0; }
2017.字符串统计
#include <stdio.h> #include <string.h> int main(){ int n; char c[10000]; scanf("%d",&n); while(n>0){ scanf("%s",c); int i; int count=0; for(i=0;i<strlen(c);i++){ if(c[i]>='0'&&c[i]<='9') count++; } printf("%d\n",count); n--; } return 0; }
2018.母牛的故事
观察出规律:
第几天 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
增加的母牛数量 | 1 | 1 | 1 | 1 | 2 | 3 | 4 | 6 | 9 |
#include <stdio.h> int main(){ int n; scanf("%d",&n); while(n!=0){ if(n<=4){ printf("%d\n",n); }else{ int a[n]; int i; int j; for(i=0;i<n;i++){ a[i]=0; } a[0]=a[1]=a[2]=a[3]=1; for(i=4;i<n;i++){ for(j=0;j<i-2;j++){ a[i]+=a[j]; } } int ans=0; for(i=0;i<n;i++){ ans+=a[i]; } printf("%d\n",ans); } scanf("%d",&n); } return 0; }
2019.数列有序
#include <stdio.h> int main(){ int n,m; scanf("%d %d",&n,&m); while(n!=0||m!=0){ int i; int t; int flag=0; for(i=0;i<n;i++){ scanf("%d",&t); if(t>m&&i!=n-1&&flag==0){ flag=1; printf("%d %d ",m,t); }else if(t>m&&i==n-1&&flag==0){ flag=1; printf("%d %d",m,t); }else if(i==n-1&&flag==1){ printf("%d",t); }else{ printf("%d ",t); } } if(flag==0) printf("%d",m); printf("\n"); scanf("%d %d",&n,&m); } return 0; }
2020.绝对值有序
#include <stdio.h> #include <math.h> void sort(int a[],int n){ int i,j; for(i=0;i<n;i++){ for(j=i+1;j<n;j++){ if(abs(a[i])<abs(a[j])){ int t=a[i]; a[i]=a[j]; a[j]=t; } } } } int main(){ int n; scanf("%d",&n); while(n!=0){ int a[n]; int i; for(i=0;i<n;i++) scanf("%d",&a[i]); sort(a,n); for(i=0;i<n;i++){ if(i==n-1) printf("%d\n",a[i]); else printf("%d ",a[i]); } scanf("%d",&n); } return 0; }
2021.发工资咯
#include <stdio.h> int main(){ int n; scanf("%d",&n); while(n!=0){ int i; int t; int count=0; for(i=0;i<n;i++){ scanf("%d",&t); int a=t/100; int b=(t-a*100)/50; int c=(t-a*100-b*50)/10; int d=(t-a*100-b*50-c*10)/5; int e=(t-a*100-b*50-c*10-d*5)/2; int f=t-a*100-b*50-c*10-d*5-e*2; count+=a+b+c+d+e+f; } printf("%d\n",count); scanf("%d",&n); } return 0; }
2022.海选女主角
本质:二维数组
#include <stdio.h> #include <math.h> int main(){ int m,n; while(scanf("%d %d",&m,&n)!=EOF){ int i,j; int a[m][n]; int x=0; int y=0; for(i=0;i<m;i++){ for(j=0;j<n;j++){ scanf("%d",&a[i][j]); if(abs(a[i][j])>abs(a[x][y])){ x=i; y=j; } } } printf("%d %d %d\n",x+1,y+1,a[x][y]); } return 0; }
2023.求平均成绩
#include <stdio.h> int main(){ int n,m; while(scanf("%d %d",&n,&m)!=EOF){ int i,j; int a[n][m]; double b[n]; double c[m]; for(i=0;i<n;i++){ int sum=0; for(j=0;j<m;j++){ scanf("%d",&a[i][j]); sum+=a[i][j]; } b[i]=sum*1.0/m; } for(i=0;i<m;i++){ int sum=0; for(j=0;j<n;j++){ sum+=a[j][i]; } c[i]=sum*1.0/n; } int count=0; for(i=0;i<n;i++){ int flag=1; for(j=0;j<m;j++){ if(a[i][j]<c[j]){ flag=0;break; } } if(flag==1) count++; } for(i=0;i<n;i++){ if(i!=n-1) printf("%.2f ",b[i]); else printf("%.2f\n",b[i]); } for(i=0;i<m;i++){ if(i!=m-1) printf("%.2f ",c[i]); else printf("%.2f\n",c[i]); } printf("%d\n\n",count); } return 0; }
2024.C语言合法标识符
输入输出是本题难点
C语言标识符是由字母(大小写),数字,或者下划线,但首字母不能够是数字
C语言中如何让空格也作为字符串输入?
解答:要输入带空格的字符串,要用到一个格式字符:%[] --> 一个字符集。
“%[]”的作用是扫描字符集合:
例如:scanf(“%[^\n]”,str);
具体作用是:如果输入的字符属于方括号内字符串中某个字符,那么就提取该字符;如果一经发现不属于就结束提取。该方法会自动加上一个'\0'到已经提取的字符后面。
函数gets(字符数组)也可以
#include <stdio.h> #include <string.h> int judge(char a){ if(a>='a'&&a<='z'){ return 1; }else if(a>='A'&&a<='Z'){ return 1; }else if(a>='0'&&a<='9'){ return 1; }else if(a=='_'){ return 1; } return 0; } int judgePrim(char a){ if(a>='a'&&a<='z'){ return 1; }else if(a>='A'&&a<='Z'){ return 1; }else if(a=='_'){ return 1; } return 0; } int main(){ int n; while(scanf("%d",&n)!=EOF){ int i,j; for(i=0;i<n;i++){ getchar(); char a[50]; scanf("%[^\n]",a); int flag=1; if(judgePrim(a[0])==0){ printf("no\n"); continue; } for(j=1;j<strlen(a);j++){ if(judge(a[j])==0){ printf("no\n"); flag=0; break; } } if(flag==1) printf("yes\n"); } } return 0; }
2025.查找最大元素
题目说的不清楚,最大元素是否忽略大小写
#include <stdio.h> #include <string.h> int main(){ char a[100]; while(scanf("%s",a)!=EOF){ int i; char max=a[0]; for(i=1;i<strlen(a);i++){ if(max<a[i]) max=a[i]; } for(i=0;i<strlen(a);i++){ if(a[i]==max) printf("%c(max)",a[i]); else printf("%c",a[i]); } printf("\n"); } return 0; }
2026.首字母变大写
#include <stdio.h> #include <string.h> int main(){ char a[100]; while(gets(a)){ int i; for(i=0;i<strlen(a);i++){ if(i==0) a[i]=(char)(a[i]-32); else if(a[i]==' ') a[i+1]=(char)(a[i+1]-32); } for(i=0;i<strlen(a);i++){ printf("%c",a[i]); } printf("\n"); } return 0; }
2027.统计元音
#include <stdio.h> #include <string.h> int main(){ int n; scanf("%d",&n); getchar(); while(n>0){ char c[100]; gets(c); int a=0; int e=0; int i=0; int o=0; int u=0; int j; for(j=0;j<strlen(c);j++){ if(c[j]=='a') a++; else if(c[j]=='e') e++; else if(c[j]=='i') i++; else if(c[j]=='o') o++; else if(c[j]=='u') u++; } printf("a:%d\n",a); printf("e:%d\n",e); printf("i:%d\n",i); printf("o:%d\n",o); printf("u:%d\n",u); if(n!=1) printf("\n"); n--; } return 0; }
2028.最小公倍数
两个数的最大公因数:辗转相除法
最小公倍数=两个数相乘除以最大公因数
对于多个数,尝试一下穷举(不行)
多个数的最小公倍数并不等于所有的数相乘除以最大公因数(eg 1 2 3 4)
正确解法:两个数处理求出最小公倍数
【注】这里有一个很坑的点(搞了好久)求两个数最小公倍数的时候,先一个数除以最大公因数再乘另外一个数,不然会溢出,结果错误。
#include <stdio.h> int gcd(int a,int b){ if(a==0) return b; if(b==0) return a; return a>b?gcd(a%b,b):gcd(a,b%a); } int main(){ int n; while(scanf("%d",&n)!=EOF){ if(n==1){ int t; scanf("%d",&t); printf("%d\n",t); }else{ int a[n]; int i; for(i=0;i<n;i++){ scanf("%d",&a[i]); } a[1]=a[0]/gcd(a[0],a[1])*a[1]; for(i=2;i<n;i++){ a[i]=a[i-1]/gcd(a[i-1],a[i])*a[i]; } printf("%d\n",a[n-1]); } } return 0; }
2029.回文串
#include <stdio.h> #include <string.h> int main(){ int n; scanf("%d",&n); getchar(); while(n-->0){ char a[100]; gets(a); int i,j; if(strlen(a)%2==0){ for(i=strlen(a)/2-1,j=strlen(a)/2;i>=0;i--,j++){ if(a[i]!=a[j]){ printf("no\n"); break; } } }else{ for(i=strlen(a)/2-1,j=strlen(a)/2+1;i>=0;i--,j++){ if(a[i]!=a[j]){ printf("no\n"); break; } } } if(i==-1){ printf("yes\n"); } } return 0; }
2030.汉字统计
如何统计汉字?
答:汉字机内码在计算机的表达方式的描述是,使用二个字节,每个字节最高位一位为1。(计算机组成原理的内容)
计算机中,补码第一位是符号位,1 表示为负数,所以 汉字机内码的每个字节表示的十进制数都是负数。
所以这题也就可以简化为输入字符串判断其中字符转化为十进制数是否小于零。
注意:汉字是有两个小于零的字符组成,所以在统计结果的时候就要将count除以2了。
#include <stdio.h> #include <string.h> int main(){ int n; scanf("%d",&n); getchar(); while(n-->0){ char a[500]; gets(a); int count=0; int i; for(i=0;i<strlen(a);i++){ int t=(int)a[i]; if(t<0) count++; } printf("%d\n",count/2); } return 0; }
2031.进制转换
注意:处理一下负数
#include <stdio.h> #include <math.h> int main(){ int n,r; char a[16]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; while(scanf("%d %d",&n,&r)!=EOF){ int i=0; char b[50]; if(n<0) printf("-"); n=abs(n); while(n!=0){ b[i++]=a[n%r]; n=n/r; } int j; for(j=i-1;j>=0;j--){ printf("%c",b[j]); } printf("\n"); } return 0; }
2032.杨辉三角
OJ对于输出非常严格,不可以有多余的空格
#include <stdio.h> int main(){ int n; while(scanf("%d",&n)!=EOF){ int a[n][n]; int i,j; for(i=0;i<n;i++){ a[i][0]=1;a[i][i]=1; } for(i=2;i<n;i++){ for(j=1;j<i;j++){ a[i][j]=a[i-1][j]+a[i-1][j-1]; } } for(i=0;i<n;i++){ for(j=0;j<=i;j++){ if(j!=i) printf("%d ",a[i][j]); else printf("%d",a[i][j]); } printf("\n"); } printf("\n"); } return 0; }
2033.人见人爱A+B
#include <stdio.h> int main(){ int n; scanf("%d",&n); while(n-->0){ int ah,bh,am,bm,as,bs; scanf("%d %d %d %d %d %d",&ah,&am,&as,&bh,&bm,&bs); int flag=0; int ch=0; int cm=0; int cs=0; if(as+bs>=60){ cs=as+bs-60; flag=1; }else{ cs=as+bs; } if(am+bm+flag>=60){ cm=am+bm+flag-60; flag=1; }else{ cm=am+bm+flag; flag=0; } ch=ah+bh+flag; printf("%d %d %d\n",ch,cm,cs); } return 0; }
2034.人见人爱A-B
两个集合通过数组来存储,进行快排,然后折半查找。
#include <stdio.h> int partition(int a[],int low,int high){ int pivot=a[low]; while(low<high){ while(low<high&&a[high]>=pivot) high--; a[low]=a[high]; while(low<high&&a[low]<=pivot) low++; a[high]=a[low]; } a[low]=pivot; return low; } void quicksort(int a[],int low,int high){ if(low<high){ int p=partition(a,low,high); quicksort(a,low,p-1); quicksort(a,p+1,high); } } int binarySearch(int a[],int key,int low,int high){ int mid; while(low<=high){ mid=(low+high)/2; if(a[mid]==key) return mid; else if(a[mid]<key) low=mid+1; else if(a[mid]>key) high=mid-1; } return -1; } int main(){ int n,m; scanf("%d %d",&n,&m); while(n!=0||m!=0){ int a[n]; int b[m]; int i; for(i=0;i<n;i++){ scanf("%d",&a[i]); } quicksort(a,0,n-1); for(i=0;i<m;i++){ scanf("%d",&b[i]); } quicksort(b,0,m-1); int flag=0; for(i=0;i<n;i++){ int t=binarySearch(b,a[i],0,m-1); if(t==-1){ printf("%d ",a[i]); flag=1; } } if(flag==0){ printf("NULL\n"); }else{ printf("\n"); } scanf("%d %d",&n,&m); } return 0; }
2035.人见人爱A^B
#include <stdio.h> int main(){ int a,b; scanf("%d %d",&a,&b); while(a!=0||b!=0){ int ans=1; int i; for(i=0;i<b;i++){ ans=ans*a%1000; } printf("%d\n",ans); scanf("%d %d",&a,&b); } return 0; }
2036.改革春风吹满地
已知多边形各顶点坐标如何求面积 解答
#include <stdio.h> int main(){ int n; scanf("%d",&n); while(n!=0){ int x[n]; int y[n]; int i; for(i=0;i<n;i++){ scanf("%d %d",&x[i],&y[i]); } double ans=0; for(i=0;i<n;i++){ if(i!=n-1) ans=ans+(x[i]*y[i+1]-x[i+1]*y[i]); else ans=ans+(x[i]*y[0]-x[0]*y[i]); } printf("%.1f\n",ans*0.5); scanf("%d",&n); } return 0; }
2037.今年暑假不AC
自己做的时候,并没有想到贪心策略,说明还是练得太少
思路:按照结束时间排序,结束时间一样的不需要处理,因为要么不选这个节目,要么只能选择其中一个。
#include <stdio.h> void sort(int a[],int b[],int n){ int i,j; for(i=0;i<n;i++){ for(j=i+1;j<n;j++){ if(b[i]>b[j]){ int t=b[i]; b[i]=b[j]; b[j]=t; t=a[i]; a[i]=a[j]; a[j]=t; } } } } int main(){ int n; scanf("%d",&n); while(n!=0){ int start[n]; int end[n]; int i; for(i=0;i<n;i++){ scanf("%d %d",&start[i],&end[i]); } sort(start,end,n); int ans=1; int time=end[0]; for(i=1;i<n;i++){ if(time<=start[i]){ ans++; time=end[i]; } } printf("%d\n",ans); scanf("%d",&n); } return 0; }
2039.三角形
#include <stdio.h> #include <math.h> int main(){ int m; scanf("%d",&m); while(m-->0){ double a,b,c; scanf("%lf %lf %lf",&a,&b,&c); if(((a+b)>c)&&(a+c)>b&&(b+c)>a&&abs(a-b)<c&&abs(a-c)<b&&abs(b-c)<a){ printf("YES\n"); }else{ printf("NO\n"); } } return 0; }
2040.亲和数
#include <stdio.h> int f(int a){ int i; int sum=0; for(i=1;i<a;i++){ if(a%i==0) sum=sum+i; } return sum; } int main(){ int m; scanf("%d",&m); while(m-->0){ int a,b; scanf("%d %d",&a,&b); if(f(a)==b&&f(b)==a) printf("YES\n"); else printf("NO\n"); } return 0; }
2041.超级楼梯
思路:走楼梯,递归 结果:超时,考虑优化
级数 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
结果 | 1 | 2 | 3 | 5 | 8 | 13 | 21 |
很容易发现规律
2042.不容易系列之二
跟2013几乎一样
#include <stdio.h> int main(){ int n; scanf("%d",&n); while(n-->0){ int a; scanf("%d",&a); int i; int ans=3; for(i=0;i<a;i++){ ans=(ans-1)*2; } printf("%d\n",ans); } return 0; }
2043.密码
考察对于字符串的操作
不知道问题出在哪里,就是测不过
2044.一只小蜜蜂
跟走楼梯一样
递归超时,找规律后,还是超时
优化,用数组,结果有点大要用long long存储 long都不够
#include <stdio.h> int main(){ int n; scanf("%d",&n); long long c[50]; int i; c[1]=1; c[2]=2; for(i=3;i<50;i++){ c[i]=c[i-1]+c[i-2]; } while(n-->0){ int a,b; scanf("%d %d",&a,&b); printf("%lld\n",c[b-a]); } return 0; }
2045.不容易系列之(3)—— LELE的RPG难题
第一次想不出来
要找出递推关系 看解答
n=1 3
n=2 3*2=6
n=3 3*2*1=6
n>=4 根据n-1的情况 f(n-1)表示第一块和第n-1块颜色不同一共涂色方法
f(n-2)表示第一块和第n-2块涂色不同 与n-1块涂色下相同
所以 f(n)=f(n-1)+2*f(n-2)
结果可能很大,要用long long保存
#include <stdio.h> int main(){ int n; long long a[51]; int i; a[1]=3; a[2]=6;a[3]=6; for(i=4;i<51;i++){ a[i]=a[i-1]+2*a[i-2]; } while(scanf("%d",&n)!=EOF){ printf("%lld\n",a[n]); } }
2046.骨牌铺方格
f(1)=1 f(2)=2 f(3)=3
n>=4 f(n)=f(n-1)+f(n-2)
#include <stdio.h> int main(){ int n; long long a[51]; a[1]=1; a[2]=2; a[3]=3; int i; for(i=4;i<51;i++){ a[i]=a[i-1]+a[i-2]; } while(scanf("%d",&n)!=EOF){ printf("%lld\n",a[n]); } return 0; }
2047.阿牛的EOF牛肉串
f(1)=3 f(2)=2*2+2*2=8
找不出递推式,这方面比较差
n>=3 最后一个字符可以是E或者F,如果最后一个字符是O,倒数第二个字符是E或者F
f(n)=f(n-1)*2+f(n-2)*2
#include <stdio.h> int main(){ int n; long long a[40]; a[1]=3;a[2]=8; int i; for(i=3;i<40;i++){ a[i]=2*a[i-1]+2*a[i-2]; } while(scanf("%d",&n)!=EOF){ printf("%lld\n",a[n]); } return 0; }
2048.神、上帝以及老天爷
本质:求n!,以及排列组合
思考:n封信,不拿到自己信的概率
n张纸条分给n个人,一共有n!种情况(排队)
每个人不拿到自己名字的纸条(考虑逆)n!-(n-2)!*n (不正确)
经典的错排问题,若有n-1个人都没有拿到自己的名字,再来一个人拿着自己的名字,可以和这n-1个人中的任意一个交换手中的名字,于是便可以得到n个人都不拿自己名字的情况。还有一种就是,n-1个人中,n-2个人拿的不是自己的名字,有一个拿的是自己的名字,再来一个人和这一个人互换名字,于是就可以得到n个人都不拿自己名字的情况。
#include <stdio.h> int main(){ long long b[21]; b[1]=1; int i; for(i=2;i<21;i++){ b[i]=i*b[i-1]; } long long c[21]; c[2]=1; c[3]=2; for(i=4;i<21;i++){ c[i]=(i-1)*(c[i-1]+c[i-2]); } int n; scanf("%d",&n); while(n-->0){ int a; scanf("%d",&a); double result=c[a]*100.0/b[a]; printf("%.2f%%\n",result); } return 0; }
2049.不容易系列之(4)——考新郎
将其转换成2048题
根据测试数据推出,不可以同时找一个新娘
要么不找错,要么至少两对出现错误
考虑m对找错的情况(跟2048就一样了):f(2)=1 f(3)=2
#include <stdio.h> int main(){ long long a[21]; a[0]=1;a[1]=1; int i; for(i=2;i<21;i++){ a[i]=i*a[i-1]; } long long b[21]; b[2]=1;b[3]=2; for(i=4;i<21;i++){ b[i]=(b[i-1]+b[i-2])*(i-1); } int c; scanf("%d",&c); while(c-->0){ int n,m; scanf("%d %d",&n,&m); printf("%lld\n",a[n]/(a[m]*a[n-m])*b[m]); } return 0; }
2050.折线分割平面
这题感觉还是很有难度的。
看了别人写的解答
首先考虑直线分割平面 解答 这个比较好理解一些
把折线看成两条射线
记住这个定理,每增加n个交点,就多出来n+1块区域。
所以每增加一个折线,就要增加4*(n-1)+1个区域 解答
#include <stdio.h> int main(){ int c; scanf("%d",&c); int a[10001]; int i; a[1]=2; for(i=2;i<10001;i++){ a[i]=a[i-1]+4*(i-1)+1; } while(c-->0){ int n; scanf("%d",&n); printf("%d\n",a[n]); } return 0; }
2051.Bitset
将十进制转换为二进制
#include <stdio.h> int main(){ int n; while(scanf("%d",&n)!=EOF){ int a[100]; int i=0; while(n/2!=0||n==1){ a[i]=n%2; n=n/2; i++; } int j; for(j=i-1;j>=0;j--){ printf("%d",a[j]); } printf("\n"); } return 0; }
2052.Picture
循环,没什么难的
#include <stdio.h> int main(){ int n,m; while(scanf("%d %d",&n,&m)!=EOF){ int i,j; for(i=0;i<=m+1;i++){ for(j=0;j<=n+1;j++){ if((i==0&&j==0)||(i==0&&j==n+1)||(i==m+1&&j==0)||(i==m+1&&j==n+1)) printf("+"); else if(i==0||i==m+1) printf("-"); else if(j==0||j==n+1) printf("|"); else printf(" "); if(j==n+1) printf("\n"); } } printf("\n"); } return 0; }
2053.Switch Game
输出无数次实验后第n个台灯的状态
暴力解法,超时,
想第n次实验的约数
n=4 约数有1,2 开,关,开 根据奇偶性
#include <stdio.h> int main(){ int n; while(scanf("%d",&n)!=EOF){ int i; int count=0; for(i=1;i<n;i++){ if(n%i==0) count++; } if(count%2==0) printf("1\n"); else printf("0\n"); } return 0; }
2054.A == B ?
看似简单,还是不怎么好处理 ,复杂,要考虑全面
5.000 和5 是不是就是一样的
要是两个数很大,很长怎么办,所以输入要用char[] 同时要考虑以上情况
char *strstr(const char *str1, const char *str2);
eg.
if(strstr(a,".")==0)
判断a数组中是否有"."(小数点) 自己循环实现也可以
strcmp(a,b) 比较两个字符数组是否相同
少了一种情况 去掉前面的无效0(需要通过指针实现,不然要往前移挺麻烦的) 暂时使用的还是这种
需要字符指针的操作
0.0 0
000.0 0
放一下,自己写的代码太复杂,逻辑混乱
2055.An easy problem
接收字符前的数据要getchar()掉,这一点调试了很久。
#include <stdio.h> int change(char a){ if(a>='A'&&a<='Z'){ return (int)(a-'A')+1; }else if(a>='a'&&a<='z'){ char temp=(char)(a-32); int t=change(temp); return -1*t; } } int main(){ int t; scanf("%d",&t); getchar(); while(t-->0){ char a; int b; scanf("%c %d",&a,&b); printf("%d\n",change(a)+b); getchar(); } return 0; }
2056.Rectangles
考虑两个矩形位置的所有情况
极端,考虑相交和不相交
输入处理:左侧矩形 然后右侧 对角线的两个点要统一,都是/
多画图,本题较麻烦的是输入处理。
不清楚,哪里错误。
2057.A+B Again
十六进制加减法
一种思路,转换成十进制,再把结果转成十六进制,很麻烦
令一种思路,相十进制加减法一样处理,先算低位,再算高位。 符号处理
考虑复杂
int main(){ int a,b; while(scanf("%X %X",&a,&b)!=EOF){ printf("%X\n",a+b); } return 0; }
%X输入十六进制数
这种方式,结果为正数没有问题,负数结果用的是补码,需要改一下
又出现一个问题 输入的数比较大时 不行
C语言内置可以处理十六进制的方法,如下:
用%x/%X
%x表示小写%X表示大写。
如果数字比较大 由int改成__int64(两个下划线)
对该变量的读写也要相应的改成%I64x或者%I64X
#include <stdio.h> int main(){ __int64 a,b; while(scanf("%I64X %I64X",&a,&b)!=EOF){ if(a+b>=0){ printf("%I64X\n",a+b); }else{ printf("-%I64X\n",-a-b); } } return 0; }
2058.The sum problem
暴力解法,估计会超时
不能够从1开始枚举到m,就要用到等差数列,对数学要求还是很高
首先推项数j:
首项为a,( a+a+j-1)*b/2=m 可以推出项数j<=sqrt(2*m)
然后根据项数j,和求出首项
题目补充一个条件:N>M
“sqrt”: 对重载函数的调用不明确 解决方法:在参数上加上类型
#include <stdio.h> #include <math.h> int main(){ int n,m; scanf("%d %d",&n,&m); while(n!=0&&m!=0){ int j; for(j=(int)sqrt((double)2*m);j>=1;j--){ int i=((2*m)/j+1-j)/2; if((i+i+j-1)*j==2*m){ printf("[%d,%d]\n",i,i+j-1); } } printf("\n"); scanf("%d %d",&n,&m); } return 0; }
2059.龟兔赛跑
一维数组的动态规划
有一点比较难理解:
从起点出发(第0站)
#include <stdio.h> int main(){ int L; while(scanf("%d",&L)!=EOF){ int n,c,t; scanf("%d%d%d",&n,&c,&t); int v1,v2,v3; scanf("%d%d%d",&v1,&v2,&v3); int p[150]; //n+2个点,给常数,Oj会编译错误 int i; p[0]=0; for(i=1;i<=n;i++){ scanf("%d",&p[i]); } p[n+1]=L;//特别处理一下 double t1=L*1.0/v1;//兔子所用时间 double dp[150];//n+2个点,最后用dp[n+1]和t1做比较,oj会编译错误 dp[0]=0; int j; for(i=1;i<n+2;i++){ double min=L*1.0/v3; for(j=0;j<i;j++){ //从j点到i点的情况 double ans; int len=p[i]-p[j]; if(len>c){ //中途会没电 ans=c*1.0/v2+(len-c)*1.0/v3; }else{ //一路有电 ans=len*1.0/v2; } ans+=dp[j];//加上前面所花时间 if(j>0){ //除去起点,要加上充电时间 ans+=t; } min=min>ans?ans:min; } dp[i]=min; //printf("经过第%d点所花时间%.2f\n",i,dp[i]); } //printf("兔子所花时间:%.2f\n",t1); //printf("乌龟所花时间:%.2f\n",dp[n+1]); if(dp[n+1]<t1){ printf("What a pity rabbit!\n"); }else{ printf("Good job,rabbit!\n"); } } return 0; }
2060.Snooker
没玩过
#include <stdio.h> int main(){ int n; scanf("%d",&n); while(n-->0){ int c,s1,s2; scanf("%d %d %d",&c,&s1,&s2); if(c>6){ //大于6个球,先打红再打黑(1+7) 然后所有彩色球 7+6+5+4+3+2=27 s1+=8*(c-6)+27; }else{ //小于6个求按顺序打 int i=7; while(c-->0){ s1+=i; i--; } } if(s1>=s2) printf("Yes\n"); else printf("No\n"); } return 0; }
2061.Treasure the new start, freshmen
很简单 看清楚输出格式
#include <stdio.h> int main(){ int n; scanf("%d",&n); while(n--){ int c; scanf("%d",&c); getchar(); double b[1000];//学分 double d[1000];//分数 int flag=0;//是否有不及格 int i=0; while(c--){ char a[30]; scanf("%s %lf %lf",a,&b[i],&d[i]); //printf("分数:%f\n",d[i]); if(d[i]<60) flag=1; i++; } if(flag==1) printf("Sorry!\n"); else{ double ans=0; double sum=0; int j; for(j=0;j<i;j++){ sum+=b[j]; ans+=b[j]*d[j]; } printf("%.2lf\n",ans/sum); } if(n!=0) printf("\n"); } return 0; }
2062.Subset sequence
要发现规律,有点困难
首先一共有几个子集很容易,使用排列组合
n=1 1*1=1
n=2 (1+1)*2=4
n=3 (4+1)*3=15
n=4 (14+1)*4=64
搞清楚在哪个组
我测了几个数据,没有问题,但就是Runtime Error(ACCESS_VIOLATION)
2063.过山车
挺难的,什么二分图最大匹配算法
2064.汉诺塔III
想一下怎么移动
①将上面的n-1个转盘移动到最右侧杆上
②将第n个转盘放到中间杆上
③将最右侧杆上的n-1个转盘移回到最左侧杆
④将中间杆上第n个转盘移动最右侧杆
⑤将最左侧的n-1个圆盘移回到最右侧杆
f(1)=2;
f(2)=f(1)+1+f(1)+1+f(1);
f(n)=3*f(n-1)+2;
#include <stdio.h> int main(){ long long a[36]; int i; a[1]=2; for(i=2;i<=35;i++){ a[i]=3*a[i-1]+2; } int n; while(scanf("%d",&n)!=EOF){ printf("%lld\n",a[n]); } return 0; }
2065."红色病毒"问题
比较麻烦的递推题
分析:
将长度为n的字符串类型分为一下几类:
合法的字符串(A出现次数为偶数个,C出现次数也为偶数个) f[n][0]
A出现次数为奇数个,C出现次数为偶数个的不合法字符串 f[n][1]
A出现次数为偶数个,C出现次数为奇数个的不合法字符串 f[n][2]
A出现次数为奇数个,C出现次数为奇数个的不合法字符串 f[n][3]
f[n][0]=f[n-1][0]*2+f[n-1][1]+f[n-1][2]
f[n][1]=f[n-1][0]+f[n-1][3]+f[n-1][1]*2
f[n][2]=f[n-1[0]+f[n-1][3]+f[n-1][2]*2
f[n][3]=f[n-1][1]+f[n-1][2]
f[n][0]+f[n][1]+f[n][2]+f[n][3]=4^n
f[n][1]=f[n][2]
n=1时
f[1][0]=2
f[1][1]=1
f[1][2]=1
f[1][3]=0
这样还求不出来,n给出的太大,还得转弯
并且迭代过程对数学要求高,要动笔算
2^2 和2^22最后两位一样,开始出现循环
2^64longlong 放的下吗 可以 注意一下输出格式空格什么的
#include <stdio.h> #include <math.h> int f(long long n){ int temp=(n-2)%20+2; int a[]={1,2,4,8,16,32,64,28,56,12,24,48,96,92,84,68,36,72,44,88,76,52}; return a[temp]; } int main(){ int t; scanf("%d",&t); while(t!=0){ int i=1; while(i<=t){ long long n; scanf("%lld",&n); int ans=(f(2*n-2)+f(n-1))%100; printf("Case %d: %d\n",i,ans); i++; } printf("\n"); scanf("%d",&t); } }
2066
放一下
2067.小兔的棋盘
卡特兰数:入栈序列为1,2,3,4,...n,出栈序列有C(2n,n)/(n+1)
但使用这种不怎么理解,也用使用动态规划做的
输出搞的太复杂,一开始没看懂
关于对角线对称,考虑一半就好了
#include <stdio.h> int main(){ int n; scanf("%d",&n); __int64 a[40][40]; int i,j; for(i=0;i<40;i++){ //第0列 第0行一种走法 a[i][0]=1; a[0][i]=1; } for(i=1;i<40;i++){ //记录下三角 for(j=1;j<=i;j++){ if(i==j) a[i][j]=a[i][j-1]; else a[i][j]=a[i-1][j]+a[i][j-1]; } } int k=1; while(n!=-1){ printf("%d %d %I64d\n",k,n,a[n][n]*2); k++; scanf("%d",&n); } }
2068.RPG的错排
排错问题升级版
答对一半或者以上,就是打错小于一半
思路没有错误,但n=20以上就可能因为数字太大出现错误
计算阶乘,20以上都太大,超出范围,需要换一种方法求组合数
#include <stdio.h> int c(int n,int m){ int a=1; int i; for(i=1;i<=m;i++){ a=a*(n-i+1); a/=i; } return a; } int main(){ __int64 a[26]; a[1]=1;a[2]=1; a[3]=2; int i; for(i=4;i<=14;i++){ //26已经超出,其实用不到26 a[i]=(i-1)*(a[i-1]+a[i-2]); //n-1个人没拿到自己的纸条,来了一个人拿了自己的纸条,和这n-1其中一个交换,或者是 // n-2个人中n-1个没拿到自己纸条,一个人拿到自己纸条,来一个人纸条交换 } //计算阶乘,20以上都太大,超出范围,需要换一种方法求组合数 int n; scanf("%d",&n); while(n!=0){ int j; __int64 sum=1;//全部正确 for(j=2;j<=n/2;j++){ //排错 sum+=c(n,j)*a[j]; } printf("%I64d\n",sum); scanf("%d",&n); } return 0; }
2069.Coin Change
暴力解法
总的硬币数量要小于等于100
#include <stdio.h> int main(){ int n; while(scanf("%d",&n)!=EOF){ int i,j,k,w; int ans=0; for(i=n/50;i>=0;i--){ //50元 for(j=(n-i*50)/25;j>=0;j--){//25元 for(k=(n-i*50-j*25)/10;k>=0;k--){//10元 for(w=(n-i*50-j*25-k*10)/5;w>=0;w--){//5元 if((n-i*50-j*25-k*10-w*5+i+j+k+w)<=100){//1元 ans++; } } } } } printf("%d\n",ans); } return 0; }
2070.Fibbonacci Number
#include <stdio.h> int main(){ __int64 a[51]; a[0]=0;a[1]=1; int i; for(i=2;i<51;i++){ a[i]=a[i-1]+a[i-2]; } int n; scanf("%d",&n); while(n!=-1){ printf("%I64d\n",a[n]); scanf("%d",&n); } return 0; }
2071.Max Num
简单题
#include <stdio.h> int main(){ int n; scanf("%d",&n); while(n--){ int t; scanf("%d",&t); int i; double max=0.00; for(i=0;i<t;i++){ double temp; scanf("%lf",&temp); if(temp>max) max=temp; } printf("%.2lf\n",max); } return 0; }
2072.单词数
使用java因为对于C++/C的库函数不清楚
测试了一下,不知道哪里错误
错误原因:两个单词之间不一定只有一个空格,所以按空格拆分的时候要注意一下
import java.util.*; public class Test8 { public static void main(String[] args) { String str; Scanner scan=new Scanner(System.in); str=scan.nextLine(); while(!str.equals("#")){ String temp[]=str.split(" +"); Set<String> set=new HashSet<>(); for(int i=0;i<temp.length;i++){ set.add(temp[i]); } System.out.println(set.size()); str=scan.nextLine(); } } }
2073.无限的路
求浮点数的绝对值fabs()函数
数组要开大一点,光计算到点(0,100)不可以 (100,100)再后面呢
#include <stdio.h> #include <math.h> int main(){ //试着求出所有点到(0,0)点的距离 double a[400][400]; a[0][0]=0; int i,j; int x=0; int y=0;//记录上一个点 for(j=1;j<=399;j++){ for(i=0;i<=j;i++){ int t=(y-j+i)*(y-j+i)+(x-i)*(x-i); a[i][j-i]=a[x][y]+sqrt((double)t); x=i;y=j-i; } } int n; scanf("%d",&n); while(n--){ int x1,y1,x2,y2; scanf("%d%d%d%d",&x1,&y1,&x2,&y2); printf("%.3lf\n",fabs(a[x1][y1]-a[x2][y2])); } return 0; }
2074.叠筐
找规律,输出图形
坑:特殊处理n=1,还得注意一下输出
#include <stdio.h> void draw(int n,char a,char b){ int i,j,k; char c[80][80]; k=n/2+1; for(i=0;i<k;i++){//圈数 for(j=i;j<n-i;j++){ //第一行 if((k-i+1)%2==0){ c[i][j]=a; }else{ c[i][j]=b; } } for(j=i;j<n-i;j++){ //最后一行 if((k-i+1)%2==0){ c[n-i-1][j]=a; }else{ c[n-i-1][j]=b; } } for(j=i+1;j<n-i-1;j++){//最左列 if((k-i+1)%2==0){ c[j][i]=a; }else{ c[j][i]=b; } } for(j=i+1;j<n-i-1;j++){//最右列 if((k-i+1)%2==0){ c[j][n-i-1]=a; }else{ c[j][n-i-1]=b; } } } //特殊处理 c[0][0]=' ';c[n-1][n-1]=' ';c[0][n-1]=' ';c[n-1][0]=' '; //输出 for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ printf("%c",c[i][j]); } printf("\n"); } } int main(){ int n; char a,b; int flag=0; while(scanf("%d",&n)!=EOF){ getchar(); scanf("%c",&a); getchar(); scanf("%c",&b); if(flag){ printf("\n"); } if(n==1){ printf("%c\n",a); }else{ draw(n,a,b); } flag=1; } return 0; }
2075.A|B?
#include <stdio.h> int main(){ int t; scanf("%d",&t); while(t--){ long long a,b; scanf("%lld%lld",&a,&b); if(a%b==0){ printf("YES\n"); }else{ printf("NO\n"); } } return 0; }
2076.夹角有多大
秒钟转一圈为1min,1个小时转360/12=30 那么秒钟转一圈就是30/60=0.5
秒钟转一圈相当于分钟转360/60=6
注意:夹角是0-180度
#include <stdio.h> #include <math.h> int main(){ int t; scanf("%d",&t); while(t--){ int h,m,s; scanf("%d%d%d",&h,&m,&s); //先计算时钟与0的夹角 double t1; h=h%12; t1=30*h+m*1.0/60*30+s*1.0/60*0.5; //printf("t1======%.1f\n",t1); double t2; t2=m*1.0/60*360+1.0*6*s/60; //printf("t2======%.1f\n",t2); double t=fabs(t1-t2); if(t>180){ t=360-t; } int ans=(int) t; printf("%d\n",ans); //结果不要四舍五入,保留整数即可 } return 0; }
2077.汉诺塔IV
汉诺塔变形
允许最大的盘子放到最上面
按照规则,将上面n-1个盘无需移动到最右侧,移动到中间即可
然后将最大盘移动到中间,再从中间移动到右侧
问题就转换为:按照以前规则,n个盘从左侧移动到中间移动的最小次数
f(n)=f(n-1)+f(n-1)+1+f(n-1)=3*f(n-1)+1 f(1)=1
所以,g(n)=2*f(n-1)+2
#include <stdio.h> #include <math.h> int main(){ int a[21]; a[0]=0; a[1]=1; int i; for(i=2;i<=20;i++){ a[i]=3*a[i-1]+1; } int t; scanf("%d",&t); while(t--){ int n; scanf("%d",&n); printf("%d\n",2*a[n-1]+2); } return 0; }
2078.复习时间
#include <stdio.h> int main(){ int t; scanf("%d",&t); while(t--){ int n,m; scanf("%d %d",&n,&m); int i; int min=100; for(i=0;i<n;i++){ int x; scanf("%d",&x); if(x<min) min=x; } printf("%d\n",(100-min)*(100-min)); } return 0; }
2079.选课时间
最多8个学分,每个学分最多10门课
纯暴力,八重循环依次列举
#include <stdio.h> int main(){ int t; scanf("%d",&t); int c[9]; int i; for(i=0;i<9;i++){ c[i]=0; } while(t--){ int n,u; scanf("%d %d",&n,&u); for(i=0;i<u;i++){ int x1,y1; scanf("%d%d",&x1,&y1); c[x1]=y1;//表示第x个学分的课程有y个 } int ans=0; int i,j,k,w,l,x,y; //暴力 for(i=0;i<=n/8&&i<=c[8];i++){ for(j=0;j<=(n-8*i)/7&&j<=c[7];j++){ for(k=0;k<=(n-8*i-7*j)/6&&k<=c[6];k++){ for(w=0;w<=(n-8*i-7*j-6*k)/5&&w<=c[5];w++){ for(l=0;l<=(n-8*i-7*j-6*k-5*w)/4&&l<=c[4];l++){ for(x=0;x<=(n-8*i-7*j-6*k-5*w-4*l)/3&&x<=c[3];x++){ for(y=0;y<=(n-8*i-7*j-6*k-5*w-4*l-3*x)/2&&y<=c[2];y++){ if((n-8*i-7*j-6*k-5*w-4*l-3*x-2*y)<=c[1]) { ans++; } } } } } } } } printf("%d\n",ans); } return 0; }
2080.夹角有多大II
actan() C语言 atan()
#include <math.h> #define PI 3.1415926 double change(double x1,double y1){ double t1=0.0; if(x1<0&&y1!=0){ t1=180-atan(fabs(y1)/fabs(x1))*180/PI; } else if(x1>0&&y1!=0){ t1=atan(fabs(y1)/fabs(x1))*180/PI; }else if(x1==0){ t1=90.0; }else if(x1<0&&y1==0){ t1=180.0; } return t1; } int main(){ int t; scanf("%d",&t); while(t--){ double x1,y1,x2,y2; scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); double t1=change(x1,y1); double t2=change(x2,y2); double ans=fabs(t1-t2); if(ans>180){ ans=360-ans; } printf("%.2f\n",ans); } return 0; }
2081.手机短号
有点过分简单
#include <stdio.h> #include <string.h> int main(){ int n; scanf("%d",&n); while(n--){ char a[11]; scanf("%s",a); a[5]='6'; int i; for(i=5;i<11;i++){ printf("%c",a[i]); } printf("\n"); } return 0; }
2082.找单词
经典的母函数题目,没接触过
26个单词 也就是26个砝码,每个砝码重量不尽相同 每种砝码数量不同
要求总价值小于等于50,那么就将构成价值1-50的系数相加
代码不对,放一下。
2083.简易版之最短距离
#include <stdio.h> #include <iostream> #include <algorithm> #include <math.h> using namespace std; int main(){ int m; scanf("%d",&m); while(m--){ int n; scanf("%d",&n); int a[500]; int i; for(i=0;i<n;i++){ scanf("%d",&a[i]); } sort(a,a+n);//排序 int start; int ans=0; if(n%2==1){ //是奇数 start=a[n/2]; for(i=0;i<n;i++){ ans+=abs(a[i]-start); } }else{//是偶数 int t1=0; start=a[n/2-1]; for(i=0;i<n;i++){ t1+=abs(a[i]-start); } int t2=0; start=a[n/2]; for(i=0;i<n;i++){ t2+=abs(a[i]-start); } ans=min(t1,t2); } printf("%d\n",ans); } return 0; }
2084.数塔
贪心算法(每次选大的那条路)结果不一定是正确的
DP用来解决最优化问题。动态规划将原始的问题分为若干个子问题,通过综合子问题的最优解,来得到原始问题的最优解。动态规划会将每个求解过的子问题的解记录下来,下次遇到同样的问题,可以直接使用。一般使用递归和递推的写法来写动态规划。
递推
5
8 3
12 7 16
4 10 11 6
从第一层走到第n层,路径上所有数字相加的和最大是多少。
令dp[i][j](我们称它为状态)表示从第i行第j列到最底层的路径上数字相加得到的最大和。想求出dp[i][j],需求两个子问题,即从(i+1,j)到达最底层的最大和dp[i+1][j]和从(i+1,j+1)到达最底层的最大和dp[i+1][j+1]。所以dp[i][j]=max(dp[i+1][j+1],dp[i+1][j])+f[i][j](这个方程称之为状态转移方程)。数塔最后一层的dp值,等于元素本身,dp[n][j]=f[n][j],把这种可以直接确定结果的部分称之为边界。动态规划的递推写法就是从边界出发,通过状态转移方程扩散到整个dp数组。
#include <stdio.h> int max(int a,int b){ return a>b?a:b; } int main(){ int c; scanf("%d",&c); int dp[100][100]; while(c--){ int n; scanf("%d",&n); int i,j; for(i=0;i<n;i++){ for(j=0;j<=i;j++){ scanf("%d",&dp[i][j]); } } //自下而上 for(i=n-2;i>=0;i--){ for(j=0;j<=i;j++){ dp[i][j]+=max(dp[i+1][j],dp[i+1][j+1]); } } printf("%d\n",dp[0][0]); } }
2085.核反应堆
简单题
#include <stdio.h> using namespace std; int main(){ int n; scanf("%d",&n); while(n!=-1){ long long a=1; long long b=0;//初始值 int i=0; for(i=0;i<n;i++){ long long t=a*3+2*b; b=1*a+1*b; a=t; } printf("%lld, %lld\n",a,b); scanf("%d",&n); } return 0; }
2086.A1=?
数学对公式进行推导,发现规律
#include <stdio.h> int main(){ int n; while(scanf("%d",&n)!=EOF){ double a,b; scanf("%lf%lf",&a,&b); double c[3000]; int i; for(i=0;i<n;i++){ scanf("%lf",&c[i]); } double ans=0.0; int x=2*n; double temp=0.0; for(i=0;i<n;i++){ temp+=x*c[i]; x=x-2; } ans=(n*a+b-temp)/(n+1); printf("%.2lf\n",ans); } return 0; }
2087.剪花布条
字符匹配
#include <stdio.h> #include <string.h> #include <string> #include <iostream> using namespace std; int main(){ char a[1000]; char b[1000]; scanf("%s",a); while(a[0]!='#'){ scanf("%s",b); int ans=0; for(int i=0;i<strlen(a);i++){ int temp=i;//用一个临时变量记录i for(int j=0;j<strlen(b);j++){ if(a[temp]!=b[j]){ break;//跳出循环 }else{ temp++;//匹配下一个字符 if(j==strlen(b)-1){//说明全部匹配上了 ans++; i=i+strlen(b)-1; } } } } printf("%d\n",ans); scanf("%s",a); } return 0; }
2088.Box of Bricks
#include <stdio.h> int main(){ int n; scanf("%d",&n); int flag=0; while(n!=0){ if(flag){ printf("\n");//为了格式 } int i,j; int a[50]; int sum=0; int ans=0;//记录移动的次数 for(i=0;i<n;i++){ scanf("%d",&a[i]); sum+=a[i]; } int avg=sum/n;//一定是整除的 for(int i=0;i<n;i++){ while(a[i]<avg){ //找后面大的搬过来 for(j=i+1;j<n;j++){ if(a[j]>avg){ a[i]=a[i]+1; a[j]=a[j]-1; ans++; break;//跳出for循环 } } } while(a[i]>avg){ //把大的搬到小的上面 for(j=i+1;j<n;j++){ if(a[j]<avg){ a[i]=a[i]-1; a[j]=a[j]+1; ans++; break;//跳出 for循环 } } } } printf("%d\n",ans); flag=1; scanf("%d",&n); } return 0; }
2089.不要62
用java 字符串处理比较简单
使用contains()方法,超时了,性能差
使用indexof()方法 还是超时了
那就一个数一个数判断是否含有4或者62 还超时 10的七次方还是慢了一点
事先确定好数的个数 牺牲空间
#include <stdio.h> bool judge(int t){ while(t!=0){ if(t%10==4||t%100==62){ return false; } t=t/10; } return true; } int main(){ int a[1000000]; //devc++申请不了这么大的数组 ,但oj能过 a[0]=0; int i; for(i=1;i<1000000;i++){ if(judge(i)){ a[i]=a[i-1]+1; }else{ a[i]=a[i-1]; } } int n,m; scanf("%d %d",&n,&m); while(n!=0||m!=0){ printf("%d\n",a[m]-a[n-1]); scanf("%d %d",&n,&m); } return 0; }
最后,很荣幸能够被杭州电子科技大学计算机学院拟录取,愿自己不忘初心,继续加油!