当前位置:   article > 正文

西工大2023新版C语言NOJ(持续更新中)_nojcsdn

nojcsdn

引言

第一篇博客,用以记录自己学习的过程,欢迎大佬们批评指正,期待更好的算法和更优化的代码。

本篇内容仅供交流学习,读者因其他用途造成的一切后果与本人无关。

Hello world

  1. #include<stdio.h>
  2. int main()
  3. {
  4. //注意大小写和空格
  5. printf("Hello World");
  6. return 0;
  7. }

 A+B

  1. #include<stdio.h>
  2. int main()
  3. {
  4. int a,b;
  5. scanf("%d %d",&a,&b);
  6. printf("%d",a + b);
  7. return 0;
  8. }

数据类型大小及范围

  1. #include<stdio.h>
  2. #include<limits.h>
  3. int main()
  4. {
  5. int a;
  6. scanf("%d",&a);
  7. //注意数值和输出类型匹配
  8. if( a == 1 ) printf("%d,%d,%d",sizeof(char),CHAR_MIN,CHAR_MAX);
  9. if( a == 2 ) printf("%d,0,%u",sizeof(unsigned char),UCHAR_MAX);
  10. if( a == 3 ) printf("%d,%d,%d",sizeof(short),SHRT_MIN,SHRT_MAX);
  11. if( a == 4 ) printf("%d,0,%u",sizeof(unsigned short),USHRT_MAX);
  12. if( a == 5 ) printf("%d,%d,%d",sizeof(int),INT_MIN,INT_MAX);
  13. if( a == 6 ) printf("%d,0,%u",sizeof(unsigned int),UINT_MAX);
  14. if( a == 7 ) printf("%d,%ld,%ld",sizeof(long),LONG_MIN,LONG_MAX);
  15. if( a == 8 ) printf("%d,0,%lu",sizeof(unsigned long),ULONG_MAX);
  16. if( a == 9 ) printf("%d,%lld,%lld",sizeof(long long),LLONG_MIN,LLONG_MAX);
  17. if( a == 10 ) printf("%d,0,%llu",sizeof(unsigned long long),ULLONG_MAX);
  18. return 0;
  19. }

平均值

  1. #include<stdio.h>
  2. int main()
  3. {
  4. //选择范围较大的数据类型
  5. long long a,b;
  6. scanf("%lld %lld",&a,&b);
  7. printf("%lld",(a + b)/2);
  8. return 0;
  9. }

进制转换

  1. #include<stdio.h>
  2. int main()
  3. {
  4. long long a;
  5. scanf("%lld",&a);
  6. //X为大写
  7. printf("%X,%o",a,a);
  8. return 0;
  9. }

浮点数输出

  1. #include<stdio.h>
  2. int main()
  3. {
  4. double a;
  5. scanf("%lf",&a);
  6. printf("%.6lf,%.2lf,%.8lf",a,a,a);
  7. return 0;
  8. }

动态宽度输出

  1. #include<stdio.h>
  2. int main()
  3. {
  4. long long m,n,a;
  5. int w = 0;
  6. scanf("%lld %lld",&m,&n);
  7. a = m;
  8. //获得m的位数
  9. while(a != 0)
  10. {
  11. w++;
  12. a = a/10;
  13. }
  14. if(n > w)
  15. {
  16. for(int i = 1;i <= (n - w);i++)
  17. {
  18. printf("0");
  19. }
  20. printf("%lld",m);
  21. }
  22. else printf("%lld",m);
  23. return 0;
  24. }

计算地球上两点之间的距离

  1. #include<stdio.h>
  2. #include<math.h>
  3. #define PI 3.14159265358979323846
  4. #define R 6371
  5. int main()
  6. {
  7. //latitude纬度 longitude经度
  8. double longi1,lati1,longi2,lati2,dlongi,dlati;
  9. double a,d;
  10. scanf("%lf %lf\n%lf %lf",&lati1,&longi1,&lati2,&longi2);
  11. //注意将角度转化为弧度再进行计算
  12. longi1 = longi1 * (PI /180.0);
  13. lati1 = lati1 * (PI / 180.0);
  14. longi2 = longi2 * ( PI /180.0);
  15. lati2 = lati2 * (PI / 180.0);
  16. dlongi = longi2 - longi1;
  17. dlati = lati2 - lati1;
  18. a = pow(sin(dlati / 2),2) + cos(lati1) * cos(lati2) * pow(sin(dlongi / 2),2);
  19. d = 2 * R * asin(sqrt(a));
  20. printf("%.4lfkm",d);
  21. return 0;
  22. }

风寒指数

%g表示自动舍去小数后不必要的0,整数则直接输出整数

  1. #include<stdio.h>
  2. #include<math.h>
  3. int main()
  4. {
  5. double ws,at,wc;
  6. double a,b,c;
  7. scanf("%lf %lf",&ws,&at);
  8. a = 0.6215 * at;
  9. b = 11.37 * pow(ws,0.16);
  10. c = 0.3965 * at * pow(ws,0.16);
  11. wc = 13.12 + a - b + c;
  12. wc = round(wc);
  13. printf("%g",wc);
  14. return 0;
  15. }

颜色模型转换

  1. #include<stdio.h>
  2. #include<math.h>
  3. int main()
  4. {
  5. unsigned int R,G,B;
  6. double r,g,b,maxi,mini,d;
  7. double H,S,V;
  8. scanf("%u %u %u",&R,&G,&B);
  9. //应先将R,G,B范围转化为(0,1)
  10. //转化关系可上网自行搜索,即/255
  11. r = R / 255.0;
  12. g = G / 255.0;
  13. b = B / 255.0;
  14. maxi = g;
  15. mini = g;
  16. if(r > maxi) maxi = r;
  17. if(b > maxi) maxi = b;
  18. if(r < mini) mini = r;
  19. if(b < mini) mini = b;
  20. d = maxi - mini;
  21. V = maxi;
  22. if(V != 0) S = d / maxi;
  23. //注意讨论V是否为0
  24. else S = 0;
  25. if(d != 0)
  26. {
  27. //注意小数尽量不要直接比较(float不能比较,但double与long double型可以)
  28. //可以将两数差值与极小数进行比较,判定是否相等
  29. //1e-9表示1*10^-9
  30. if(maxi - r < 1e-9)
  31. {
  32. H = (g - b) / d;
  33. }
  34. if(maxi - g < 1e-9)
  35. {
  36. H = 2 + (b - r) / d;
  37. }
  38. if(maxi - b < 1e-9)
  39. {
  40. H = 4 + (r - g) / d;
  41. }
  42. H = H * 60;
  43. if(H < 0)
  44. {
  45. H += 360;
  46. }
  47. }
  48. //不要遗漏H可能为0的情况
  49. else H = 0;
  50. printf("%.4lf,%.4lf%%,%.4lf%%",H,S * 100,V * 100);
  51. return 0;
  52. }

方阵

 方法一:思路为以0为分割
 左边递减输出,右边递增输出

  1. # include <stdio.h>
  2. int main(void)
  3. {
  4. int i,n;
  5. scanf("%d",&n);
  6. for (i=0; i<n; ++i)
  7. {
  8. printf("%d",i);//先输出第一个数,解决末尾空格问题
  9. for(int j=i-1;j>-1;j--)
  10. {
  11. printf(" %d",j);
  12. }
  13. for(int g=1;g<n-i;g++)
  14. {
  15. printf(" %d",g);
  16. }
  17. printf("\n");
  18. }
  19. return 0;
  20. }

方法二:利用绝对值!    (思路来自“rivenkki”)

  1. #include<stdio.h>
  2. #include<math.h>
  3. int main()
  4. {
  5. int a;
  6. scanf("%d",&a);
  7. for(int i =0;i<a;++i)
  8. {
  9. int m=i;
  10. for(int j=0;j<a;++j)
  11. {
  12. printf("%d ",abs(m));
  13. m -= 1;
  14. }
  15. printf("\n");
  16. }
  17. return 0;
  18. }

对称数

此题解法很有意思,是对switch用法很好的诠释。

简单解释一下switch:

我们清楚switch(p)中p为预判定的式子,计算机将自动判断p与case后设定的东西是否相等,但我们需要理解的是case语句只是提供了一个执行switch内语句的接口,这里就涉及到了break的作用。

以此题为例:

若p=0,显然他与case 0相符合,那么这时这个case 0后的语句就将被依次执行,直到遇到了第一个break语句,那么此次switch语句框架结束,立刻退出switch执行 switch外的代码。                       

若p=6,那则从case 6后开始执行,到第一个break结束并退出switch。

从这篇文章里学习到的:c语言switch中break语句的作用

  1. #include<stdio.h>
  2. int main()
  3. {
  4. int n,p,bn,r = 0;
  5. scanf("%d",&n);
  6. bn = n;
  7. while(bn > 0)
  8. {
  9. p = bn % 10;
  10. switch(p)
  11. {
  12. //0,1,8,6,9才可能构成对称数,3,4,7显然不可能构成对称数
  13. //另外此题认为2,5,也无法构成
  14. case 0:
  15. case 1:
  16. case 8:r = r * 10 + p;break;
  17. //6,9旋转发生变化,因此单独考虑
  18. case 6:r = r * 10 + 9;break;
  19. case 9:r = r * 10 + 6;break;
  20. default:printf("No");return 0;
  21. //r = r * + ;的操作是在进行书的翻转
  22. //即最后一位变成第一位,倒数第二位变成第二位,以此类推
  23. }
  24. bn = bn / 10;
  25. }
  26. if(n == r) printf("Yes");
  27. else printf("No");
  28. return 0;
  29. }

乘数模

直接相乘再mod可能会超出数据上限,可分别mod相乘再mod,可自行证明。

  1. #include<stdio.h>
  2. int main()
  3. {
  4. long long a,b,m;
  5. scanf("%lld %lld %lld",&a,&b,&m);
  6. printf("%lld",(a % m) * (b % m) % m);
  7. return 0;
  8. }

比率

思路为把小数部分乘10^c变为整数后作为分子,再将分母设为10^c进行约分

  1. #include<stdio.h>
  2. #include<math.h>
  3. int main()
  4. {
  5. double n,g;
  6. long long fz,fm,d,c=0,b=0,x,tfz,tfm;
  7. scanf("%lf",&n);
  8. int k = 0;
  9. g = n;
  10. //求出小数位数c
  11. while(k != g)
  12. {
  13. g *= 10;
  14. k = (int)g;
  15. c++;
  16. }
  17. fm =pow(10,c);
  18. fz = n * pow(10,c);
  19. tfz = fz;
  20. tfm = fm;
  21. //获得最大公约数x(‘分数的加减乘除法’中提供了另一种更为简单求法)
  22. while(tfz % 2 == 0&&tfm % 2 ==0)
  23. {
  24. tfz /= 2;
  25. tfm /= 2;
  26. b++;
  27. }
  28. //更相减损术
  29. while(tfz != tfm)
  30. {
  31. if(tfz > tfm) tfz -= tfm;
  32. else tfm -= tfz;
  33. }
  34. x = pow(2,b) * tfz;
  35. //进行约分
  36. fz /= x;
  37. fm /= x;
  38. printf("%d/%d",fz,fm);
  39. return 0;
  40. }

分数的加减乘除法

利用递归求m,n的最大公约数(太强了qwq)

注意三点:

1.考虑结果为1时的输出  

2.考虑减法分子为0时的输出  

3.考虑减法结果为负的输出

  1. #include<stdio.h>
  2. #include<math.h>
  3. //辗转相除法,可自行代数检验
  4. int gcd(int m,int n)
  5. {
  6. if(n == 0) return m;
  7. else return gcd(n,m % n);
  8. }
  9. int main()
  10. {
  11. long a,b,c,d;
  12. long m,n;
  13. long t;
  14. scanf("%ld/%ld\n%ld/%ld",&a,&b,&c,&d);
  15. //加法
  16. m = a * d + c * b;
  17. n = b * d;
  18. t = gcd(m,n);
  19. m /= t;
  20. n /= t;
  21. if(m == n) printf("(%ld/%ld)+(%ld/%ld)=1\n",a,b,c,d);
  22. else printf("(%ld/%ld)+(%ld/%ld)=%ld/%ld\n",a,b,c,d,m,n);
  23. //减法
  24. m = a * d - c * b;
  25. n = b * d;
  26. t = abs(gcd(m,n));//将最大公约数取绝对值保证结果为负数时,输出的正确性
  27. m /= t;
  28. n /= t;
  29. if(m == 0) printf("(%ld/%ld)-(%ld/%ld)=0\n",a,b,c,d);
  30. else if(m == n) printf("(%ld/%ld)-(%ld/%ld)=1\n",a,b,c,d);
  31. else printf("(%ld/%ld)-(%ld/%ld)=%ld/%ld\n",a,b,c,d,m,n);
  32. //乘法
  33. m = a * c;
  34. n = b * d;
  35. if(m == n) printf("(%ld/%ld)*(%ld/%ld)=1\n",a,b,c,d);
  36. else
  37. {
  38. t = gcd(m,n);
  39. m /= t;
  40. n /= t;
  41. printf("(%ld/%ld)*(%ld/%ld)=%ld/%ld\n",a,b,c,d,m,n);
  42. }
  43. //除法
  44. m = a * d;
  45. n = b * c;
  46. if(m == n) printf("(%ld/%ld)/(%ld/%ld)=1\n",a,b,c,d);
  47. else
  48. {
  49. t = gcd(m,n);
  50. m /= t;
  51. n /= t;
  52. printf("(%ld/%ld)/(%ld/%ld)=%ld/%ld\n",a,b,c,d,m,n);
  53. }
  54. return 0;
  55. }

组合数

  1. #include<stdio.h>
  2. int main()
  3. {
  4. int n,c;
  5. scanf("%d",&n);
  6. for(int i=0;i<10;i++)
  7. {
  8. for(int j=0;j<10;j++)
  9. {
  10. for(int g=0;g<10;g++)
  11. {
  12. for(int w=0;w<10;w++)
  13. {
  14. if((i+j+g+w)==n) c++;
  15. }
  16. }
  17. }
  18. }
  19. printf("%d",c);
  20. return 0;
  21. }

级数和

  1. #include<stdio.h>
  2. int main()
  3. {
  4. int n;
  5. double t,sum = 0;
  6. scanf("%d",&n);
  7. for(int i=1;i<n+1;i++)
  8. {
  9. if(i==1)
  10. {
  11. sum = sum + 1.2;
  12. printf("1.2");
  13. }
  14. else if(i<9)
  15. {
  16. t = i + (i+1)/10.0;
  17. sum = sum + t;
  18. printf("+%g",t);
  19. }
  20. else if(i<99)
  21. {
  22. t = i + (i+1)/100.0;
  23. sum = sum + t;
  24. printf("+%g",t);
  25. }
  26. else
  27. {
  28. sum = sum + 99.1;
  29. printf("+99.1");
  30. }
  31. }
  32. printf("=%g",sum);
  33. return 0;
  34. }

倍数和

方法一:

注意去重,及既能被3整除又能被5整除的数(代码较长,速度较快)

  1. #include<stdio.h>
  2. //获得小于n的所有自然数中3和5的倍数之和
  3. unsigned int sum(unsigned int a)
  4. {
  5. long long h = 0,i=0,j=0,g=0;
  6. while((3*i)<a) i++;
  7. while((5*j)<a) j++;
  8. while((15*g)<a) g++;
  9. h = 3*i*(i-1) + 5*j*(j-1) - 15*g*(g-1);
  10. return h/2;
  11. }
  12. int main()
  13. {
  14. int t;
  15. scanf("%d",&t);
  16. unsigned int a[t+1];
  17. for(int i=1;i<=t;i++)
  18. {
  19. //利用数组循环输入
  20. unsigned int n;
  21. scanf("\n%u",&n);
  22. a[i] = n;
  23. }
  24. for(int i=1;i<=t;i++)
  25. {
  26. //利用数组循环输出
  27. if(i == 1) printf("%u",sum(a[i]));
  28. else printf("\n%u",sum(a[i]));
  29. }
  30. return 0;
  31. }

方法二:

不用去重(代码较短,速度较长)

  1. #include<stdio.h>
  2. int main()
  3. {
  4. long long t;
  5. scanf("%lld",&t);
  6. unsigned int a[t];
  7. for(int i=0;i<t;i++) scanf("%lld",&a[i]);
  8. for(int i=0;i<t;i++)
  9. {
  10. long long sum=0;
  11. for(int j=1;j<a[i];j++)
  12. {
  13. if(j%3==0||j%5==0) sum = sum + j;
  14. }
  15. printf("%lld\n",sum);
  16. }
  17. return 0;
  18. }

幂数模

此题学到很多新东西,初步涉及了一点算法问题

为了避免对a全部幂运算再取模超出数值范围,采取快速模幂运算,用到了二进制指数法和分治算法的思想

以13为例进行简单的说明:

13的二进制表示为1101,正常情况下如果要计算a^13,需进行13次乘法,为了减少计算时间,我们对算法进行优化

13=1×2^3+1×2^2+0×2^1+1×2^0,假设最终结果为r,不难发现,当二进制位数为0时,我们可以先不将r乘2,而是让a自乘(即a=a×a,相当于a^2^n,n每次加1),同时进行向右按位位移1位的操作(即>>=1),那么若右移后的最低位为1,我们便将r乘此时的a,这样就能使得运算次数减少。

详细解释一下,欲求5^13

  1. while(b != 0)
  2. {
  3. //b&1:用来判断当前b的二进制最低位是否为1
  4. //若为1,则累乘
  5. if(b & 1) t = t * a;
  6. //否则,只是将a自乘,并不与最终结果t累乘
  7. a = (a * a);
  8. //将b向右按位位移1位
  9. b >>= 1;
  10. }
  11. /*初始b=13=(1101)B=2^3+2^2+2^0=8+4+1,a=5,t=1
  12. 第一次
  13. b&1=0001 为真
  14. if条件成立 t=t*5=1*5
  15. a=a*a=5^2
  16. b=110
  17. 第二次
  18. b&1=000 为假
  19. if不成立 t=1*5不变
  20. a=a*a=5^2*5^2=5^4
  21. b=11
  22. 第三次
  23. b&1=01 为真
  24. if条件成立 t=t*a=1*5*5^4
  25. a=a*a=5^4*5^4=5^8
  26. b=1
  27. 第四次
  28. b&1=1 为真
  29. if条件成立 t=t*a=1*5*5^4*5^8=5^(2^0+2^2+2^3)*/

感觉本质就在于把指数分解为二进制

具体操作是通过b&1判断和b>>=1,使得a自乘后的指数和二进制表示中为1的位对应的数相一致

本题答案

  1. #include<stdio.h>
  2. int main()
  3. {
  4. long long a,b,m,t = 1;
  5. scanf("%lld %lld %lld",&a,&b,&m);
  6. while(b != 0)
  7. {
  8. //b&1:用来判断当前b的二进制最低位是否为1
  9. //若为1,则累乘
  10. if(b & 1) t = (t * a) % m;
  11. //否则,只是将a自乘,并不与最终结果t累乘
  12. a = (a * a) % m;
  13. //将b向右按位位移1位
  14. b >>= 1;
  15. }
  16. printf("%lld",t);
  17. return 0;
  18. }

操作数

另一种获得位数的巧妙方法

即   位数n=(int)log10(x)  +  1

  1. #include<stdio.h>
  2. //获得各个位数之和
  3. long long wsum(long long x)
  4. {
  5. long long h = 0;
  6. while(x!=0)
  7. {
  8. h = h + (x % 10);
  9. x = x / 10;
  10. }
  11. return h;
  12. }
  13. int main()
  14. {
  15. long long n,i=0;
  16. scanf("%lld",&n);
  17. while(n>0)
  18. {
  19. n = n - wsum(n);
  20. i++;
  21. }
  22. printf("%lld",i);
  23. return 0;
  24. }

俄罗斯农夫乘法

  1. #include<stdio.h>
  2. int main()
  3. {
  4. long long m,n,sum = 0;
  5. scanf("%lld %lld",&m,&n);
  6. while(m != 0)
  7. {
  8. printf("%lld %lld\n",m,n);
  9. if((m%2) != 0) sum = sum + n;
  10. n = n * 2;
  11. m = m / 2;
  12. }
  13. printf("%lld",sum);
  14. return 0;
  15. }

余数和

  1. #include<stdio.h>
  2. int main()
  3. {
  4. int n,k,sum = 0;
  5. scanf("%d %d",&n,&k);
  6. while(n != 0)
  7. {
  8. sum = sum + k % n;
  9. n--;
  10. }
  11. printf("%d",sum);
  12. return 0;
  13. }

方案数

我们先进行数学上的运算(x = 1,2,3,...)

两个连续正整数的和:x  x+1  =  2x+1

三个连续正整数的和:x  x+1 x+2 =  3x+3

四个连续正整数的和:x  x+1  x+2  x+3=  4x+6

......

i个连续正整数的和:x  x+1  ...  x+i-2  x+i-1  =i*x+i*(i-1)/2

不难发现当(n-(i*(i-1))/2)%i == 0时,方案成立,则方案数c加1

另外需要注意的是,while循环需要停止条件t<n,因为当t>=n时,n-t<=0,x不存在

  1. #include<stdio.h>
  2. int main()
  3. {
  4. int n,i = 1,c = 0,t;
  5. scanf("%d",&n);
  6. do
  7. {
  8. if((n-(i*(i-1))/2)%i == 0) c++;
  9. i++;
  10. t = (i*(i-1))/2;
  11. }
  12. while(t<n);
  13. printf("%d",c);
  14. return 0;
  15. }

竖式乘法

  1. #include<stdio.h>
  2. //获得位数(考虑x可能为0的情况)
  3. int ws(int x)
  4. {
  5. int n=0;
  6. if(x != 0)
  7. {
  8. while(x>0)
  9. {
  10. x /= 10;
  11. n++;
  12. }
  13. }
  14. else n = 1;
  15. return n;
  16. }
  17. int main()
  18. {
  19. int a,b,t,tb,wb,c,ca,cb=0;
  20. scanf("%d %d",&a,&b);
  21. int m[b+1];
  22. tb = b;
  23. t = a * b;
  24. //获得最终结果位数
  25. c = ws(t) + 1;
  26. //获得a的位数
  27. ca = ws(a);
  28. //获得b的位数及每一位数
  29. while(tb>0)
  30. {
  31. wb = tb % 10;
  32. tb /= 10;
  33. ++cb;
  34. m[cb] = wb;
  35. }
  36. //输出前三行
  37. for(int i = 1;i <= c - ca;i++) printf(" ");
  38. printf("%d\n",a);
  39. printf("x");
  40. for(int i = 2;i <= c - cb;i++) printf(" ");
  41. printf("%d\n",b);
  42. for(int i = 1;i <= c;i++) printf("-");
  43. printf("\n");
  44. //输出运算过程
  45. for(int i = 1;i <= cb;i++)
  46. {
  47. int tr,wr;
  48. tr = a * m[i];
  49. wr = ws(tr);
  50. if(i != cb)
  51. {
  52. for(int j = 1;j <= (c - wr - i + 1);j++) printf(" ");
  53. printf("%d",tr);
  54. for(int j = 1;j <= i - 1;j++) printf(" ");
  55. printf("\n");
  56. }
  57. else
  58. {
  59. printf("+%d",tr);
  60. for(int j = 1;j <= i - 1;j++) printf(" ");
  61. printf("\n");
  62. }
  63. }
  64. for(int i = 1;i <= c;i++) printf("-");
  65. //输出最终结果
  66. printf("\n %d",t);
  67. return 0;
  68. }

好数字

数学上的排列组合

0~9中偶数有0,2,4,6,8共五个,素数有1,3,5,7共四个

同时为了避免累乘过程超出数据范围,我们每次乘4或5时都同时%mod

另:

使用mod进行取模的原因防止计算时出现溢出,相加时防止int类型溢出,相乘防止long类型溢出

同时当数值比mod小的时候,取余数,对结果不会有影响。

  1. #include<stdio.h>
  2. int main()
  3. {
  4. long long n,r=1,mod=1e9+7;
  5. scanf("%lld",&n);
  6. for(long long i=1;i<=n;++i)
  7. {
  8. if(i%2 != 0) r = (r * 5) % mod;
  9. else r = (r * 4) % mod;
  10. }
  11. printf("%lld",r);
  12. return 0;
  13. }

查找数列

为了减少循环次数,我们从a = sqrt(n)开始

因为:

√n*(√n+1)/2 = (n+√n)/ 2  <  n

  1. #include<stdio.h>
  2. #include<math.h>
  3. int main()
  4. {
  5. double n;
  6. long long a;
  7. scanf("%lf",&n);
  8. a = sqrt(n);
  9. while(((a+1)*(a+2)/2)<n) a++;
  10. printf("%g",n-a*(a+1)/2);
  11. return 0;
  12. }

最大数字 

  1. #include<stdio.h>
  2. int main()
  3. {
  4. unsigned int n;
  5. scanf("%u",&n);
  6. for(unsigned int i=n;i>0;--i)
  7. {
  8. //设置一个标志变量c
  9. unsigned int t=i,a,b,c=1;
  10. while(t>9)
  11. {
  12. a = t % 10;
  13. t /= 10;
  14. b = t % 10;
  15. if(b < a) c = 1;
  16. else c = 0;
  17. }
  18. if(c)
  19. {
  20. printf("%u",i);
  21. break;
  22. }
  23. }
  24. return 0;
  25. }

阶乘倍数

找到正确写法啦

终于不超时了!!!

梳理一下思路:

首先如果我们用嵌套for循环来遍历,直到找到符合的n的方法,会发现系统判断超时。我们需要对代码做进一步优化,降低时间复杂度。

一、

对于任一正整数来说,如果从1到sqrt(k)都没有它的因数,则该正整数在1到n上一定没有因数。

这并不难理解,我们以36举例:

1×36=36  2×18=36  3×12=36  4×9=36  6×6=36

简单来说就是,如果 i 为正整数k在1到sqrt(k)上的一个因数,那么n / i 也一定是n的一个因数。

二、

我们仔细思考一下题目的问题会发现,其实求一个最小的a满足a!是给定k的倍数,就是在找,1到n中k的所有因数里,最少相乘到哪个因数的最终结果等于k。

因为如果a!是k的倍数,那么k一定能拆解为1到a中k的因数的乘积的形式。

三、

接下来就需要找到这个最小的a了

我们采取的算法是,for循环从1遍历到sqrt(k),如果发现 i 是k的因数(即k%i==0),就将k/i,同时暂存这个目前最大的因数,如此循环,直到k被彻底拆解(即k==1),利用break语句跳出循环。

四、

那么如果在1到sqrt(k)内k没有被彻底拆解该怎么办呢?

我们只需要找到第一个大于当前最大因数y且为当前k的整数倍的数就可以了

(贴个图方便理解)

  1. #include<stdio.h>
  2. #include<math.h>
  3. int main()
  4. {
  5. long long k,s,y=1,a=1,c=1;
  6. scanf("%lld",&k);
  7. s = sqrt(k);
  8. for(long long i=2;i<=s;++i)
  9. {
  10. if(k%i==0)
  11. {
  12. k /= i;
  13. y = i;
  14. }
  15. if(k==1)
  16. {
  17. printf("%lld",i);
  18. return 0;
  19. }
  20. }
  21. do
  22. {
  23. a=k*c;
  24. c++;
  25. }
  26. while(a<=y);
  27. printf("%lld",a);
  28. return 0;
  29. }

倒水

分两种情况

一、先倒满小杯

二、先倒满大杯

我们参照题目给出例子写出详细过程后,仔细思考发现,下一步的最优操作是由本步两杯水的情况决定的,因此我们分别考虑不同的情况(存在规律),并给出下一步的运算方式

  1. #include<stdio.h>
  2. int firtype(int m,int n,int d)
  3. {
  4. int a=m,b=0,i=1;
  5. while(1)
  6. {
  7. if(a!=0&&b==0)
  8. {
  9. b=a;
  10. a=0;
  11. i++;
  12. if(a==d||b==d) break;
  13. }
  14. if(a==0&&b!=0)
  15. {
  16. a=m;
  17. i++;
  18. if(a==d||b==d) break;
  19. }
  20. if(a==m&&b!=0)
  21. {
  22. b=b+a;
  23. if(b>n)
  24. {
  25. a=b-n;
  26. b=n;
  27. }
  28. else a=0;
  29. i++;
  30. if(a==d||b==d) break;
  31. }
  32. if(a!=0&&b==n)
  33. {
  34. b=0;
  35. i++;
  36. if(a==d||b==d) break;
  37. }
  38. }
  39. return i;
  40. }
  41. int sectype(int m,int n,int d)
  42. {
  43. int a=0,b=n,i=1;
  44. while(1)
  45. {
  46. if(b==n)
  47. {
  48. b=b-(m-a);
  49. a=m;
  50. i++;
  51. if(a==d||b==d) break;
  52. }
  53. if(a==m&&b!=0)
  54. {
  55. a=0;
  56. i++;
  57. if(a==d||b==d) break;
  58. }
  59. if(a==0&&b!=0)
  60. {
  61. a=b;
  62. b=0;
  63. i++;
  64. if(a==d||b==d) break;
  65. }
  66. if(a!=0&&b==0)
  67. {
  68. b=n;
  69. i++;
  70. if(a==d||b==d) break;
  71. }
  72. }
  73. return i;
  74. }
  75. int mini(int a,int b)
  76. {
  77. return a<b?a:b;
  78. }
  79. int main()
  80. {
  81. int m,n,d,a,b;
  82. scanf("%d %d %d",&m,&n,&d);
  83. a=firtype(m,n,d);
  84. b=sectype(m,n,d);
  85. printf("%d",mini(a,b));
  86. return 0;
  87. }

毕达哥拉斯三元组

说在前面: 

调试了好久,最后发现时数据类型定义小了,把long long换成unsighed long long就顺利AC了

思路:

主要是条件的预处理:

1.c的大致范围

由a+b+c=n,a<b<c,我们可以得到c>(a+b)/2,即c>(n-c)/2,解得c>n/3

由c^2=a^2+b^2<(a+b)^2,我们可以得到c<a+b,即c<n-c,解得c<n/2

2.a的大致范围

由a<b,a^2+b^2=c^2,我们可以得到a^2<b^2,即a^2<c^2-a^2,解得a<c/√2

由a<b,a+b+c=n,我们可以得到a<n-c-a,解得a<(n-c)/2

取min{c/√2 , (n-c)/2}

  1. #include<stdio.h>
  2. #include<math.h>
  3. int mini(int x,int y)
  4. {
  5. return x<y?x:y;
  6. }
  7. int main()
  8. {
  9. //最终结果r要定义的大一些,long long会WA
  10. unsigned long long n,c,r;
  11. scanf("%llu",&n);
  12. c= n/2;
  13. for(;c>n/3;c--)
  14. {
  15. int t = mini((int)(c/sqrt(2)),(n-c)/2);
  16. for(unsigned long long a=1;a<=t+1;a++)
  17. {
  18. unsigned long long b=n-c-a;
  19. if((a*a+b*b)==c*c)
  20. {
  21. r = a*b*c;
  22. printf("%llu\n",r);
  23. break;
  24. }
  25. }
  26. }
  27. return 0;
  28. }

不知道具体什么原因,上面这个方法目前(10月12以后)无法AC了

下面这个代码目前可AC 

  1. #include<stdio.h>
  2. int main()
  3. {
  4. int n;
  5. scanf("%d",&n);
  6. for(int c=n/2;c>n/3;--c)
  7. {
  8. for(int a=1;a<n-c;++a)
  9. {
  10. int b=n-c-a;
  11. if(a*a+b*b==c*c)
  12. {
  13. printf("%d",a*b*c);
  14. return 0;
  15. }
  16. }
  17. }
  18. }

 可变参数累加

函数讲解可参考这篇文章:va_start和va_end详解

  1. #include<stdio.h>
  2. #include<stdarg.h>
  3. int sum(int n,...)
  4. {
  5. va_list ap;
  6. va_start(ap,n);
  7. int r = 0;
  8. for(int i=1;i<n;++i)
  9. {
  10. r = r + va_arg(ap,int);
  11. }
  12. va_end(ap);
  13. return r;
  14. }
  15. int main()
  16. {
  17. int a,b,c,d,e,f;
  18. int ans;
  19. scanf("%d %d %d %d %d %d",&a,&b,&c,&d,&e,&f);
  20. ans = sum(3,a,b,0)-sum(5,c,d,e,f,0);
  21. printf("%d",ans);
  22. return 0;
  23. }

基斯数

暂时不太会用内联函数,所以我选择了先不用  orz

  1. #include<stdio.h>
  2. #include<math.h>
  3. long sum(long a[],long c,long ans)
  4. {
  5. int r=0;
  6. for(int i=0;i<c;++i)
  7. {
  8. r = r + a[i];
  9. }
  10. return r;
  11. }
  12. int main()
  13. {
  14. long n,c,ans=0;
  15. scanf("%ld",&n);
  16. c=(int)log10(n)+1;
  17. long a[c],bn=n;
  18. for(int i=c-1;i>=0;--i)
  19. {
  20. a[i]=bn%10;
  21. bn /= 10;
  22. }
  23. do
  24. {
  25. ans = sum(a,c,ans);
  26. if(ans==n)
  27. {
  28. printf("Yes");
  29. return 0;
  30. }
  31. for(int i=0;i<c-1;++i)
  32. {
  33. a[i]=a[i+1];
  34. }
  35. a[c-1]=ans;
  36. }
  37. while(ans<=n);
  38. printf("No");
  39. return 0;
  40. }

运动会

思路:

能看见的条件为:班长和能看见的同学所连成的直线上没有其他的同学

以班长为(0,0),向右为x轴,向上为y轴正方向建立平面直角坐标系,则每位同学的位置可以用坐标(x,y)表示,班长能看见的同学人数,就等于与原点连线斜率第一次出现的次数

而斜率k可以表示为 \frac{x}{y} ,斜率k的最简形式为化简至分子与分母互质

问题再一次转化为在0< x,y <=n时,由x,y组成的互质坐标对数

由于是n×n的队伍,我们y=x直线两侧三角形区域中的一个就可以了,若这部分求得的互质坐标对数为r,则最终结果为2*r+1(加的1为k=1)

解决过程:

欲求出互质坐标对数,我们可以通过for循环遍历来进行,但这样会超时,于是学到了一个新的算法,即欧拉函数用于求不超过x的与x互质的数的个数

学习了这些文章:欧拉函数(Euler_Function)欧拉函数(详解)-数论欧拉函数(详细证明+推导) 每日一遍,算法再见!

先需要了解数学上关于欧拉函数的证明,可自行网上搜索学习,这里贴一下好朋友教我的简化版证明:

为什么编写Euler函数for循环截止到sqrt(n),原因在之前的题目中已经解释,这里省略

同时我们引入一个新的定理:算术基本定理

可表述为:任何一个大于1的自然数 N,如果N不为质数,那么N可以唯一分解成有限个质数的乘积

那么对n来说,从i=2开始,如果n能被i整除,我把n中的因子i都除掉后,n能被整除的下一个i一定是原n的质因数,这就是程序里面while的意义。

  1. #include<stdio.h>
  2. #include<math.h>
  3. //Eratosthenes筛法求欧拉函数
  4. int Euler(int n)
  5. {
  6. long long ans=n;
  7. for(int i=2;i<=sqrt(n);i++)
  8. {
  9. if(n%i==0)
  10. {
  11. ans=ans/i*(i-1);//先进行除法是为了防止中间数据的溢出
  12. while(n%i==0)
  13. {
  14. //除去所有因数i及i的倍数
  15. n/=i;
  16. }
  17. }
  18. }
  19. //说明还有一个质因数没算,不然n应该为1
  20. if(n>1) ans=ans/n*(n-1);
  21. return ans;
  22. }
  23. int main()
  24. {
  25. long long n,r=0;
  26. scanf("%lld",&n);
  27. for(int i=1;i<n;++i)
  28. {
  29. r = r + Euler(i);
  30. }
  31. printf("%lld",2*r+1);
  32. return 0;
  33. }

可变参数平均

  1. #include<stdio.h>
  2. #include<stdarg.h>
  3. double avg(int n,...)
  4. {
  5. double sum = 0;
  6. va_list ap;
  7. va_start(ap,n);
  8. for(int i=1;i<=n;++i)
  9. {
  10. sum = sum + va_arg(ap,double);
  11. }
  12. va_end(ap);
  13. return sum/n;
  14. }
  15. int main()
  16. {
  17. double a,b,c,d,e,ans;
  18. scanf("%lf %lf %lf %lf %lf",&a,&b,&c,&d,&e);
  19. ans = avg(2,a,b) - avg(3,c,d,e);
  20. printf("%.4lf",ans);
  21. return 0;
  22. }

佩尔数

  1. #include<stdio.h>
  2. int PA(int n)
  3. {
  4. //递归方法
  5. if(n==0) return 0;
  6. if(n==1) return 1;
  7. return 2*PA(n-1) + PA(n-2);
  8. }
  9. int PB(int n)
  10. {
  11. //递推方法
  12. int p0 = 0,p1 = 1,pn;
  13. if(n==0) pn = p0;
  14. else if(n==1) pn = p1;
  15. else
  16. {
  17. for(int i=2;i<n+1;++i)
  18. {
  19. pn = 2*p1 + p0;
  20. p0 = p1;
  21. p1 = pn;
  22. }
  23. }
  24. return pn;
  25. }
  26. int main()
  27. {
  28. int n;
  29. scanf("%d",&n);
  30. if(n%2==0) printf("%d",PB(n));
  31. else printf("%d",PA(n));
  32. return 0;
  33. }

素数

for循环全部遍历会超时

算法优化思路:

所有大于5的素数均与6的倍数相邻

证明即思路来自这篇文章:判断一个数是否为质数(素数)的4种方法

  1. #include<stdio.h>
  2. #include<math.h>
  3. //判断一个数是不是素数
  4. int PrimeNum(int x)
  5. {
  6. for(int i=3;i<=sqrt(x);i+=2)
  7. {
  8. if(x%2==0||x%i==0) return 0;
  9. }
  10. return 1;
  11. }
  12. int main()
  13. {
  14. int m,n,t,c = 0,a,b;
  15. scanf("%d %d",&m,&n);
  16. if(n==2)
  17. {
  18. printf("1");
  19. return 0;
  20. }
  21. if(n==3)
  22. {
  23. printf("2");
  24. return 0;
  25. }
  26. if(n==4)
  27. {
  28. if(m==1)
  29. {
  30. printf("2");
  31. }
  32. else printf("1");
  33. return 0;
  34. }
  35. t = m/6;
  36. while(6*t+1<m) t++;
  37. while(6*t-1<=n)
  38. {
  39. a = 6*t-1;
  40. b = 6*t+1;
  41. if(a>=m&&PrimeNum(a)) c++;
  42. if(b<=n&&PrimeNum(b)) c++;
  43. t++;
  44. }
  45. printf("%d",c);
  46. return 0;
  47. }

光线追踪

此题为洛谷原题,深入学习了洛谷大犇的写法,太太太强了!!!

提示:思考反射过程与更相减损术的联系,考虑更相减损术的几何表示

把原文放在这里:AT_agc001_b [AGC001B] Mysterious Light 题解

  1. #include<stdio.h>
  2. long long gcd(long long x,long long y)
  3. {
  4. return y==0?x:gcd(y,x%y);
  5. }
  6. int main()
  7. {
  8. long long a,n;
  9. scanf("%lld %lld",&a,&n);
  10. printf("%lld",3*(a-gcd(a,n)));
  11. return 0;
  12. }

二进制表示

想到应该要用递归,但是暂时没成功码出代码,再磨几天qwq。

看了看另一位同学的想法,思路清晰啊 orz

终于码出来了,逆向相加至所给数比正向分解所给数要简单不少

  1. #include<stdio.h>
  2. //无返回值函数的递归使用
  3. void BinaryPrest(int x)
  4. {
  5. if(x == 0)
  6. {
  7. printf("0");
  8. return;
  9. }
  10. if(x == 1)
  11. {
  12. printf("2(0)");
  13. return;
  14. }
  15. if(x == 2)
  16. {
  17. printf("2");
  18. return;
  19. }
  20. int c = 0;
  21. while((1 << (c + 1)) <= x)
  22. {
  23. c++;
  24. }
  25. if(c == 1)
  26. {
  27. printf("2");
  28. }
  29. else
  30. {
  31. printf("2(");
  32. BinaryPrest(c);
  33. printf(")");
  34. }
  35. // << 左移运算
  36. if((x - (1 << c)) != 0)
  37. {
  38. printf("+");
  39. BinaryPrest(x - (1 << c));
  40. }
  41. }
  42. int main()
  43. {
  44. int n;
  45. scanf("%d",&n);
  46. BinaryPrest(n);
  47. return 0;
  48. }

冰雹序列

  1. #include<stdio.h>
  2. int main()
  3. {
  4. int n;
  5. scanf("%d",&n);
  6. printf("%d",n);
  7. while(n!=1)
  8. {
  9. if(n%2!=0)
  10. {
  11. n = 3 * n + 1;
  12. printf(" %d",n);
  13. }
  14. else
  15. {
  16. n = n / 2;
  17. printf(" %d",n);
  18. }
  19. }
  20. return 0;
  21. }

哈沙德数

  1. #include<stdio.h>
  2. int HarshadNumber(int n)
  3. {
  4. int s=0,x=n;
  5. while(x!=0)
  6. {
  7. s = s + x % 10;
  8. x /= 10;
  9. }
  10. if(s==0||n%s!=0||n==1) return 0;
  11. else return n/s;
  12. }
  13. int main()
  14. {
  15. int n,c=0;
  16. scanf("%d",&n);
  17. while(HarshadNumber(n)!=0)
  18. {
  19. n = HarshadNumber(n);
  20. c++;
  21. }
  22. printf("%d",c);
  23. return 0;
  24. }

11月27日更新:

拖更了好久,事情太多,并且数组和字符串需要学习的新知识太多,边学边写,效率降低好多,先把AC代码贴出来,注释后续慢慢补上orz

(目前飞机起飞速度和字符串替换还未AC,据说是noj平台的问题)

回文数之和

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. int Answer(int n,int k)
  4. {
  5. int a[99],b[99],c=0,d=0,x=n,t=1;
  6. do
  7. {
  8. a[c++] = x%k;
  9. x /= k;
  10. }while(x!=0);
  11. do
  12. {
  13. b[d++] = n%10;
  14. n /= 10;
  15. }while(n!=0);
  16. for(int i=0;i<d/2;++i)
  17. {
  18. if(b[i] != b[d-i-1])
  19. {
  20. t=0;
  21. break;
  22. }
  23. }
  24. for(int i=0;i<c/2;++i)
  25. {
  26. if(a[i] != a[c-i-1])
  27. {
  28. t=0;
  29. break;
  30. }
  31. }
  32. return t;
  33. }
  34. int main()
  35. {
  36. int n,k,result=0;
  37. scanf("%d %d",&n,&k);
  38. for(int i=n-1;i>0;--i)
  39. {
  40. if(Answer(i,k)) result+=i;
  41. }
  42. printf("%d",result);
  43. return 0;
  44. }

蒙特卡洛方法求积分

想AC注意一点即可,去样本量进行计算时记得少取一个(但样本总量仍不变),如:样例2000个样本,求积分时循环取够1999个即可,这是题目本身的问题,知道就好。

知识积累:

1. C <math.h>标准库函数 double exp(double x) 返回 e 的 x 次幂的值。

2. 随机数相关知识可阅读以下文章:

    RAND_MAX的使用及rand()函数使用C语言随机函数:rand()和srand()的使用及示例

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<math.h>
  4. double Function1(double a,double b,int N,double c[])
  5. {
  6. double ans=0;
  7. for(int i=0;i<N-1;++i)
  8. {
  9. ans += c[i]*c[i]*c[i]*c[i]*(b-a)/exp(c[i]);
  10. }
  11. return ans/N;
  12. }
  13. double Function2(double a,double b,int N,double c[])
  14. {
  15. double ans=0;
  16. for(int i=0;i<N-1;++i)
  17. {
  18. ans += (c[i]*c[i]+1)*(b-a);
  19. }
  20. return ans/N;
  21. }
  22. double Function3(double a,double b,int N,double c[])
  23. {
  24. double ans=0;
  25. for(int i=0;i<N-1;++i)
  26. {
  27. ans += cos(c[i])*(b-a);
  28. }
  29. return ans/N;
  30. }
  31. double Function4(double a,double b,int N,double c[])
  32. {
  33. double ans=0;
  34. for(int i=0;i<N-1;++i)
  35. {
  36. ans += sqrt(c[i])*(c[i]-2)*(b-a);
  37. }
  38. return ans/N;
  39. }
  40. double Function5(double a,double b,int N,double c[])
  41. {
  42. double ans=0;
  43. for(int i=0;i<N-1;++i)
  44. {
  45. ans += (2*sin(c[i])-5*cos(c[i]))*(b-a);
  46. }
  47. return ans/N;
  48. }
  49. int main()
  50. {
  51. int m,N;
  52. double a,b;
  53. scanf("%d %lf %lf %d",&m,&a,&b,&N);
  54. srand(RAND_MAX);
  55. double c[N-1];
  56. for(int i=0;i<N-1;++i)
  57. {
  58. c[i] = rand()*1.0/RAND_MAX*(b-a) + a;
  59. }
  60. switch(m)
  61. {
  62. case 1:{
  63. printf("%.6lf",Function1(a,b,N,c));
  64. break;
  65. }
  66. case 2:{
  67. printf("%.6lf",Function2(a,b,N,c));
  68. break;
  69. }
  70. case 3:{
  71. printf("%.6lf",Function3(a,b,N,c));
  72. break;
  73. }
  74. case 4:{
  75. printf("%.6lf",Function4(a,b,N,c));
  76. break;
  77. }
  78. case 5:{
  79. printf("%.6lf",Function5(a,b,N,c));
  80. break;
  81. }
  82. }
  83. return 0;
  84. }

素数筛选法

下面展示的代码分别为埃氏筛的改进版与欧拉筛,实际提交测试发现,改进版的埃氏筛比欧拉筛还快上一点点

关于解决素数筛选过程中学习参考的文章如下:

埃氏筛改进版:

  1. #include<stdio.h>
  2. char a[10000000]={0};
  3. int main()
  4. {
  5. int n,ans=0;
  6. scanf("%d",&n);
  7. for(int i=2;i*i<=n;++i)
  8. {
  9. if(a[i]) continue;
  10. for(int j=i*i;j<=n;j+=i)
  11. {
  12. a[j]=1;
  13. }
  14. }
  15. for(int i=2;i<=n;++i)
  16. {
  17. if(!a[i]) ans++;
  18. }
  19. printf("%d",ans);
  20. return 0;
  21. }

欧拉筛: 

  1. #include<stdio.h>
  2. int a[10000001];
  3. int prime[10000001];
  4. int main()
  5. {
  6. int n,ans=0,cnt=0;
  7. scanf("%d",&n);
  8. for(int i=2;i<=n;++i)
  9. {
  10. if(!a[i]) prime[cnt++]=i;
  11. for(int j=0;j<cnt&&prime[j]<=n/i;++j)
  12. {
  13. a[prime[j]*i]=1;
  14. if(i%prime[j]==0) break;
  15. }
  16. }
  17. printf("%d",cnt);
  18. return 0;
  19. }

航空旅行

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. void CanorNot(int a[][5],int n)
  4. {
  5. for(int i=0;i<n;++i)
  6. {
  7. int t=0,sum=0;
  8. int m=a[i][3],n=a[i][4];
  9. for(int j=0;j<3;++j)
  10. {
  11. if(a[i][j]<=n&&a[i][j]>=t) t=a[i][j];
  12. sum += a[i][j];
  13. }
  14. if(t==0) printf("NO\n");
  15. else if((sum-t)<=m) printf("YES\n");
  16. else printf("NO\n");
  17. }
  18. }
  19. int main()
  20. {
  21. int n;
  22. scanf("%d",&n);
  23. int a[36000][5];
  24. for(int i=0;i<n;++i)
  25. for(int j=0;j<5;++j)
  26. scanf("%d",&a[i][j]);
  27. CanorNot(a,n);
  28. return 0;
  29. }

稀疏矩阵

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. int main()
  4. {
  5. int m,n,sum=0,cnt=0;
  6. int a[10000];
  7. scanf("%d %d",&m,&n);
  8. for(int i=0;i<m*n;++i)
  9. scanf("%d",&a[i]);
  10. for(int i=0;i<m*n;++i)
  11. {
  12. if(a[i]!=0) cnt++;
  13. sum += a[i];
  14. }
  15. if(cnt*20<=sum||(cnt==m||cnt==n)) printf("Yes");
  16. else printf("No");
  17. return 0;
  18. }

飞机起飞速度

暂无

完美矩阵

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int n,m;
  4. int Mini(int p,int q)
  5. {
  6. return p<q?p:q;
  7. }
  8. int Judge(int x,int y,int a[300][300])
  9. {
  10. int cnt=0;
  11. int k=Mini(n-x,m-y);
  12. for(;k>1;--k)
  13. {
  14. int cnt1=0,cnt2=0,t=1;
  15. for(int i=x;i<x+k;++i)
  16. {
  17. for(int j=y;j<y+k;++j)
  18. {
  19. if(i==x||i==(x+k-1)||j==y||j==(y+k-1))
  20. {
  21. if(a[i][j]==0)
  22. {
  23. t=0;
  24. break;
  25. }
  26. else cnt1 ++;
  27. }
  28. else
  29. {
  30. if(a[i][j]) cnt2++;
  31. else cnt2--;
  32. }
  33. }
  34. if(!t) break;
  35. }
  36. if(t)
  37. {
  38. if(cnt1==(4*k-4)&&cnt2>-2&&cnt2<2) cnt++;
  39. }
  40. }
  41. return cnt;
  42. }
  43. int main()
  44. {
  45. int sum=0;
  46. int a[300][300];
  47. scanf("%d %d",&n,&m);
  48. for(int i=0;i<n;++i)
  49. for(int j=0;j<m;++j)
  50. scanf("%d",&a[i][j]);
  51. for(int i=0;i<n-1;++i)
  52. {
  53. for(int j=0;j<m-1;++j)
  54. {
  55. if(!a[i][j]) continue;
  56. else sum += Judge(i,j,a);
  57. }
  58. }
  59. printf("%d",sum);
  60. return 0;
  61. }

行列式值

  1. #include<stdio.h>
  2. #include<math.h>
  3. int Cauclt_Det(int a[20][20],int n);
  4. int Cofactor(int a[20][20],int i,int n);
  5. int Cauclt_Det(int a[20][20],int n)
  6. {
  7. int sum=0,c;
  8. if(n==1) return a[0][0];
  9. else
  10. {
  11. for(int i=0;i<n;++i)
  12. {
  13. c = Cofactor(a,i,n);
  14. sum += pow(-1,i+2) * a[0][i] * c;
  15. }
  16. }
  17. return sum;
  18. }
  19. int Cofactor(int a[20][20],int i,int n)
  20. {
  21. int b[20][20];
  22. for(int j=0;j<n-1;++j)
  23. {
  24. for(int k=0;k<n-1;++k)
  25. {
  26. if(k<i) b[j][k] = a[j+1][k];
  27. else b[j][k] = a[j+1][k+1];
  28. }
  29. }
  30. return Cauclt_Det(b,n-1);
  31. }
  32. int main()
  33. {
  34. int n,a[20][20];
  35. scanf("%d",&n);
  36. for(int i=0;i<n;++i)
  37. for(int j=0;j<n;++j)
  38. scanf("%d",&a[i][j]);
  39. printf("%d",Cauclt_Det(a,n));
  40. return 0;
  41. }

货运优化

此为annesde的源代码,自己之前写的找不到了......

  1. #include <stdio.h>
  2. int main() {
  3. int l3s2[4] = {0, 5, 3, 1};
  4. int n, x1, x2, x3, x4, x5, x6, s2, s1;
  5. while (1) {
  6. scanf("%d %d %d %d %d %d", &x1, &x2, &x3, &x4, &x5, &x6);
  7. if ((x1 + x2 + x3 + x4 + x5 + x6) == 0) break;
  8. n = (x3 + 3) / 4 + x4 + x5 + x6;
  9. s2 = 5 * x4 + l3s2[x3 % 4];
  10. if (x2 > s2) n += (x2 - s2 + 8) / 9;
  11. s1 = 36 * n - 36 * x6 - 25 * x5 - 16 * x4 - 9 * x3 - 4 * x2;
  12. if (x1 > s1) n += (x1 - s1 + 35) / 36;
  13. printf("%d\n",n);
  14. }
  15. return 0;
  16. }

波士顿房价预测

  1. #include<stdio.h>
  2. int main()
  3. {
  4. int n;
  5. double a,b,xy=0,avrg_x=0,avrg_y=0,sqr_x=0;
  6. scanf("%d",&n);
  7. double q[n][2];
  8. for(int i=0;i<n;++i)
  9. scanf("%lf%lf",&q[i][0],&q[i][1]);
  10. for(int i=0;i<n;++i)
  11. {
  12. xy += q[i][0]*q[i][1];
  13. avrg_x += q[i][0];
  14. avrg_y += q[i][1];
  15. sqr_x += q[i][0]*q[i][0];
  16. }
  17. b = (xy - (avrg_x*avrg_y/n)) / (sqr_x - avrg_x*avrg_x/n);
  18. a = avrg_y/n - b*avrg_x/n;
  19. printf("Y=%.4lf+%.4lf*X",a,b);
  20. return 0;
  21. }

删除前后缀

  1. #include<stdio.h>
  2. #include<string.h>
  3. char *str_removeprefix(char *str,char *dstr);
  4. char *str_removesuffix(char *str,char *dstr);
  5. void Reverse_order(char *rsfs);
  6. void Reverse_order(char *rsfs)
  7. {
  8. char brsfs[100000];
  9. strcpy(brsfs,rsfs);
  10. int x=strlen(rsfs);
  11. for(int i=0;i<x;++i)
  12. {
  13. (*(rsfs+i)) = brsfs[x-i-1];
  14. }
  15. }
  16. char *str_removeprefix(char *str,char *dstr)
  17. {
  18. int len1,len2;
  19. static char *rpfs=str;
  20. len1=strlen(str);
  21. len2=strlen(dstr);
  22. int c=len1/len2;
  23. for(int i=0;i<c;++i)
  24. {
  25. int t=1;
  26. for(int j=0;j<len2;++j)
  27. {
  28. if(*(rpfs+j)!=*(dstr+j))
  29. {
  30. t=0;
  31. break;
  32. }
  33. }
  34. if(t==1) rpfs += len2;
  35. else break;
  36. }
  37. return rpfs;
  38. }
  39. char *str_removesuffix(char *str,char *dstr)
  40. {
  41. int len1,len2;
  42. static char *rsfs=str;
  43. len1=strlen(str);
  44. len2=strlen(dstr);
  45. int c=len1/len2;
  46. Reverse_order(rsfs);
  47. Reverse_order(dstr);
  48. for(int i=0;i<c;++i)
  49. {
  50. int t=1;
  51. for(int j=0;j<len2;++j)
  52. {
  53. if(*(rsfs+j)!=*(dstr+j))
  54. {
  55. t=0;
  56. break;
  57. }
  58. }
  59. if(t==1) rsfs += len2;
  60. else break;
  61. }
  62. Reverse_order(rsfs);
  63. return rsfs;
  64. }
  65. int main()
  66. {
  67. int c,p=0,d,q=0;
  68. char str[100000]="",dstr[100000]="";
  69. scanf("%[^\n] %[^\n]",str,dstr);
  70. printf("%s\n",str_removeprefix(str,dstr));
  71. printf("%s",str_removesuffix(str,dstr));
  72. return 0;
  73. }

Atol转换

  1. #include<stdio.h>
  2. #include<string.h>
  3. int main()
  4. {
  5. char str[1000]="",ans[1000]="",j=0,cnt=0,t=0;
  6. char min[]="2147483648",max[]="2147483647";
  7. scanf("%[^\n]",str);
  8. int len=strlen(str);
  9. for(int i=0;i<len;++i)
  10. {
  11. if(str[i]==' '&&t==0) continue;
  12. if(str[i]=='-'||str[i]=='+')
  13. {
  14. ans[j++]=str[i];
  15. continue;
  16. }
  17. else if(str[i]>='0'&&str[i]<='9')
  18. {
  19. ans[j++]=str[i];
  20. cnt++;
  21. t=1;
  22. continue;
  23. }
  24. else break;
  25. }
  26. ans[j]='\0';
  27. char *p=ans;
  28. if(cnt!=0)
  29. {
  30. while(*p=='0'||*p=='+') p++;
  31. if(*p=='-')
  32. {
  33. if(strlen(p+1)<strlen(min)) printf("%s",p);
  34. else if(strlen(p+1)>strlen(min)) printf("-2147483648");
  35. else
  36. {
  37. if(strcmp((p+1),min)>0) printf("-2147483648");
  38. else printf("%s",p);
  39. }
  40. }
  41. else
  42. {
  43. if(strlen(p)<strlen(max)) printf("%s",p);
  44. else if(strlen(p)>strlen(max)) printf("2147483647");
  45. else
  46. {
  47. if(strcmp(p,max)>0) printf("2147483647");
  48. else printf("%s",p);
  49. }
  50. }
  51. }
  52. else printf("0");
  53. return 0;
  54. }

大小写交换

  1. #include<stdio.h>
  2. #include<string.h>
  3. void str_swapcase(char *p)
  4. {
  5. int len=strlen(p);
  6. for(int i=0;i<len;++i)
  7. {
  8. if(*p!=' ')
  9. {
  10. if(*p>='a'&&*p<='z') *p = *p-32;
  11. else if(*p>='A'&&*p<='Z') *p = *p+32;
  12. }
  13. p++;
  14. }
  15. }
  16. int main()
  17. {
  18. char str[1000]="";
  19. scanf("%[^\n]",str);
  20. str_swapcase(str);
  21. printf("%s",str);
  22. return 0;
  23. }

前后缀移除

  1. #include<stdio.h>
  2. #include<string.h>
  3. int str_lstrip(char str[],char dstr[],int len1,int len2)
  4. {
  5. int i=0;
  6. for(;i<len1;++i)
  7. {
  8. int j=0,t=0;
  9. for(;j<len2;++j)
  10. {
  11. if(str[i] == dstr[j])
  12. {
  13. t=1;
  14. break;
  15. }
  16. }
  17. if(t==0) break;
  18. }
  19. return i;
  20. }
  21. int str_rstrip(char str[],char dstr[],int len1,int len2)
  22. {
  23. int i=len1-1;
  24. for(;i>-1;--i)
  25. {
  26. int j=0,t=0;
  27. for(;j<len2;++j)
  28. {
  29. if(str[i]==dstr[j])
  30. {
  31. t=1;
  32. break;
  33. }
  34. }
  35. if(t==0) break;
  36. }
  37. return i;
  38. }
  39. int main()
  40. {
  41. char str[100000]="",dstr[100000]="";
  42. int a,b;
  43. scanf("%[^\n] %[^\n]",str,dstr);
  44. int len1=strlen(str),len2=strlen(dstr);
  45. a=str_lstrip(str,dstr,len1,len2);
  46. b=str_rstrip(str,dstr,len1,len2);
  47. for(int i=a;i<len1;++i)
  48. printf("%c",str[i]);
  49. printf("\n");
  50. for(int i=0;i<=b;++i)
  51. printf("%c",str[i]);
  52. printf("\n");
  53. for(int i=a;i<=b;++i)
  54. printf("%c",str[i]);
  55. return 0;
  56. }

字符串替换

暂无

分离字符串

  1. #include<stdio.h>
  2. #include<string.h>
  3. int str_find(char *str,char sep[],int len1,int len2)
  4. {
  5. int i=0,j=0,m;
  6. for(;i<len1;++i)
  7. {
  8. if(*(str+i) == sep[0])
  9. {
  10. m=i;
  11. int t=1;
  12. for(int j=1;j<len2;++j)
  13. {
  14. if(*(str+i+j)!=sep[j])
  15. {
  16. t=0;
  17. break;
  18. }
  19. }
  20. if(t==0) continue;
  21. else return m;
  22. }
  23. }
  24. return -1;
  25. }
  26. void str_split(char nstr[],char *p,char sep[])
  27. {
  28. int x=strlen(p);
  29. int y=strlen(sep);
  30. int c=x/y;
  31. int j=0;
  32. for(int i=0;i<c;++i)
  33. {
  34. int cnt=str_find(p,sep,x,y);
  35. if(cnt!=-1)
  36. {
  37. for(int k=0;k<cnt;++k)
  38. {
  39. printf("%c",*(p+k));
  40. }
  41. p += (cnt+y);
  42. printf("\n");
  43. }
  44. else
  45. {
  46. printf("%s",p);
  47. return;
  48. }
  49. }
  50. }
  51. int main()
  52. {
  53. char str[2000]="",sep[20]="",nstr[2000]="";
  54. scanf("%[^\n]",str);
  55. getchar();
  56. scanf("%[^\n]",sep);
  57. str_split(nstr,str,sep);
  58. return 0;
  59. }

元宇宙A+B

第一个是我自己写的,测试数据都正确,但noj无法AC(如果有大佬发现漏洞,请务必告知,跪谢orz)

第二个是annesede的源代码(可AC),太厉害了,学习学习学习!

  1. #include<stdio.h>
  2. #include<string.h>
  3. int CtoI(char x)
  4. {
  5. switch(x)
  6. {
  7. case '0': return 0;
  8. case '1': return 1;
  9. case '2': return 2;
  10. case '3': return 3;
  11. case '4': return 4;
  12. case '5': return 5;
  13. case '6': return 6;
  14. case '7': return 7;
  15. case '8': return 8;
  16. case '9': return 9;
  17. case 'A': return 10;
  18. case 'B': return 11;
  19. case 'C': return 12;
  20. case 'D': return 13;
  21. case 'E': return 14;
  22. case 'F': return 15;
  23. case 'G': return 16;
  24. case 'H': return 17;
  25. case 'I': return 18;
  26. case 'J': return 19;
  27. case 'K': return 20;
  28. case 'L': return 21;
  29. case 'M': return 22;
  30. case 'N': return 23;
  31. case 'O': return 24;
  32. case 'P': return 25;
  33. case 'Q': return 26;
  34. case 'R': return 27;
  35. case 'S': return 28;
  36. case 'T': return 29;
  37. case 'U': return 30;
  38. case 'V': return 31;
  39. case 'W': return 32;
  40. case 'X': return 33;
  41. case 'Y': return 34;
  42. case 'Z': return 35;
  43. }
  44. }
  45. char ItoC(int y)
  46. {
  47. switch(y)
  48. {
  49. case 0: return '0';
  50. case 1: return '1';
  51. case 2: return '2';
  52. case 3: return '3';
  53. case 4: return '4';
  54. case 5: return '5';
  55. case 6: return '6';
  56. case 7: return '7';
  57. case 8: return '8';
  58. case 9: return '9';
  59. case 10: return 'A';
  60. case 11: return 'B';
  61. case 12: return 'C';
  62. case 13: return 'D';
  63. case 14: return 'E';
  64. case 15: return 'F';
  65. case 16: return 'G';
  66. case 17: return 'H';
  67. case 18: return 'I';
  68. case 19: return 'G';
  69. case 20: return 'K';
  70. case 21: return 'L';
  71. case 22: return 'M';
  72. case 23: return 'N';
  73. case 24: return 'O';
  74. case 25: return 'P';
  75. case 26: return 'Q';
  76. case 27: return 'R';
  77. case 28: return 'S';
  78. case 29: return 'T';
  79. case 30: return 'U';
  80. case 31: return 'V';
  81. case 32: return 'W';
  82. case 33: return 'X';
  83. case 34: return 'Y';
  84. case 35: return 'Z';
  85. }
  86. }
  87. int main()
  88. {
  89. char a[100]="",b[100]="",e[101]="";
  90. int c[100]={0},d[100]={0},f[101]={0};
  91. scanf("%s %s",a,b);
  92. int len1=strlen(a);
  93. int len2=strlen(b);
  94. int max=len1>len2?len1:len2;
  95. for(int i=len1-1;i>-1;--i)
  96. {
  97. c[len1-i-1]=CtoI(a[i]);
  98. }
  99. for(int i=len2-1;i>-1;--i)
  100. {
  101. d[len2-i-1]=CtoI(b[i]);
  102. }
  103. int j=0;
  104. for(int i=0;i<max;++i)
  105. {
  106. int t=c[i]+d[i];
  107. if(t<36) f[j++] += t;
  108. else
  109. {
  110. f[j++] += t-36;
  111. f[j]=1;
  112. }
  113. }
  114. int len3;
  115. if(f[j]==1) len3=j+1;
  116. else len3=j;
  117. for(int i=len3-1;i>-1;--i)
  118. {
  119. printf("%c",ItoC(f[i]));
  120. }
  121. return 0;
  122. }
  1. #include <stdio.h>
  2. #include <string.h>
  3. const static char decToMeta[37] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  4. static char c[100] = "", a[100] = "", b[100] = "";
  5. static int C[100] = {0}, A[100] = {0}, B[100] = {0};
  6. int metaToDec(char m) {
  7. if ('0' <= m && m <= '9') return m - '0';
  8. return m - 'A' + 10;
  9. }
  10. void add(void) {
  11. int lenA = strlen(a), lenB = strlen(b);
  12. for (int i = 0; i < lenA; ++i) A[i] = metaToDec(a[lenA - i - 1]);
  13. for (int i = 0; i < lenB; ++i) B[i] = metaToDec(b[lenB - i - 1]);
  14. int carry = 0;
  15. int lenC = lenA > lenB ? lenA : lenB;
  16. for (int i = 0; i < lenC; ++i) {
  17. C[i] = A[i] + B[i] + carry;
  18. carry = C[i] / 36;
  19. C[i] %= 36;
  20. }
  21. if (carry != 0) {
  22. C[lenC] = carry;
  23. ++lenC;
  24. }
  25. for (int i = lenC - 1; i >= 0; --i) c[i] = decToMeta[C[lenC - i - 1]];
  26. c[lenC] = '\0';
  27. }
  28. int main() {
  29. scanf("%s %s", a, b);
  30. add();
  31. puts(c);
  32. return 0;
  33. }

Kids A+B

  1. #include<stdio.h>
  2. #include<string.h>
  3. char eg[][10]={"zero","one","two","three","four","five",\
  4. "six","seven","eight","nine","ten","eleven","twelve","thirteen",\
  5. "fourteen","fifteen","sixteen","seventeen","eighteen","nineteen",\
  6. "twenty","thirty","forty","fifty","sixty","seventy","eighty","ninety"};
  7. int num[]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,\
  8. 30,40,50,60,70,80,90};
  9. int CtoI(char x[])
  10. {
  11. for(int i=0;i<29;++i)
  12. {
  13. if(strstr(eg[i],x)!=NULL)
  14. {
  15. if(i<20) return i;
  16. else return ((i%10)+2)*10;
  17. }
  18. }
  19. }
  20. int ItoC(int x)
  21. {
  22. for(int i=0;i<29;++i)
  23. {
  24. if(num[i]==x) return i;
  25. }
  26. }
  27. void str_split(char *p,char x[],char y[])
  28. {
  29. char *l=strstr(p,"-");
  30. if(l!=NULL)
  31. {
  32. strncpy(x,p,l-p);
  33. strcpy(y,(l+1));
  34. }
  35. else
  36. {
  37. strcpy(y,p);
  38. }
  39. }
  40. int main()
  41. {
  42. char a[15]="",b[15]="";
  43. char c[10]="",d[10]="",e[10]="",f[10]="";
  44. int m,n,p,q;
  45. scanf("%s %s",a,b);
  46. str_split(a,c,d);
  47. str_split(b,e,f);
  48. m=CtoI(c);
  49. n=CtoI(d);
  50. p=CtoI(e);
  51. q=CtoI(f);
  52. int h1,h2;
  53. h1=m+p;
  54. h2=n+q;
  55. if(h1+h2<21||(h1+h2)%10==0)
  56. {
  57. printf("%s",eg[ItoC(h1+h2)]);
  58. }
  59. else
  60. {
  61. if(h2<10)
  62. {
  63. printf("%s-%s",eg[ItoC(h1)],eg[ItoC(h2)]);
  64. }
  65. else
  66. {
  67. int t=h2/10*10;
  68. printf("%s-%s",eg[ItoC(h1+t)],eg[ItoC(h2-t)]);
  69. }
  70. }
  71. return 0;
  72. }

字符串后缀

  1. #include<stdio.h>
  2. #include<string.h>
  3. int main()
  4. {
  5. char str[100]="",sfx[100]="";
  6. scanf("%[^\n]",str);
  7. getchar();
  8. scanf("%[^\n]",sfx);
  9. int len1=strlen(str);
  10. int len2=strlen(sfx);
  11. int t=1,j=len2-1;
  12. for(int i=len1-1;i>-1;--i)
  13. {
  14. if(str[i]==sfx[j--]) break;
  15. else
  16. {
  17. t=0;
  18. break;
  19. }
  20. if(t==0) break;
  21. }
  22. if(t==1) printf("Yes");
  23. else printf("No");
  24. return 0;
  25. }

字符串切片

  1. #include<stdio.h>
  2. #include<string.h>
  3. #include<stdlib.h>
  4. void Tosame(int slc[],int len)
  5. {
  6. for(int i=0;i<2;++i)
  7. {
  8. if(slc[i]<0) slc[i] += len;
  9. }
  10. }
  11. void str_slice(char str[],int slc[],char ans[][1000],int j)
  12. {
  13. int k=0;
  14. if(slc[2]<0)
  15. {
  16. for(int i=slc[0];i>slc[1];i+=slc[2])
  17. ans[j][k++]=str[i];
  18. }
  19. else
  20. {
  21. for(int i=slc[0];i<slc[1];i+=slc[2])
  22. ans[j][k++]=str[i];
  23. }
  24. }
  25. int main()
  26. {
  27. char str[1000]="";
  28. int t;
  29. scanf("%[^\n]",str);
  30. int len=strlen(str);
  31. scanf("%d\n",&t);
  32. char ans[t][1000]={""};
  33. for(int i=0;i<t;++i)
  34. {
  35. int n,slc[3];
  36. scanf("%d",&n);
  37. if(n==1)
  38. {
  39. slc[1]=len;
  40. slc[2]=1;
  41. }
  42. if(n==2) slc[2]=1;
  43. for(int j=0;j<n;++j)
  44. {
  45. scanf(" %d",&slc[j]);
  46. }
  47. Tosame(slc,len);
  48. str_slice(str,slc,ans,i);
  49. }
  50. for(int i=0;i<t;++i) printf("%s\n",ans[i]);
  51. return 0;
  52. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/545355
推荐阅读
相关标签
  

闽ICP备14008679号