目录
算法学习
P2404 自然数的拆分问题 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)https://www.luogu.com.cn/problem/P2404
1.自然数拆分
任何一个大于 11 的自然数 nn,总可以拆分成若干个小于 nn 的自然数之和。现在给你一个自然数 nn,要求你求出 nn 的拆分成一些数字的和。每个拆分后的序列中的数字从小到大排序。然后你需要输出这些序列,其中字典序小的序列需要优先输出。
输入格式
输入:待拆分的自然数 nn。
输出格式
输出:若干数的加法式子。
输入输出样例
输入 #1复制
7输出 #1复制
1+1+1+1+1+1+1 1+1+1+1+1+2 1+1+1+1+3 1+1+1+2+2 1+1+1+4 1+1+2+3 1+1+5 1+2+2+2 1+2+4 1+3+3 1+6 2+2+3 2+5 3+41.选择dfs原因:产生排列组合,和为7,step为8,其中7个空位,第8个step为输出;
参量的设置sum,step (进入下一层);
2.终止条件:sum>7 剪枝干 (此时最终step不一定为8)
3.输出条件:sum==7,注意最后的值和前面的值输出形式不同;
4.dfs递归--for循环的设置:i为(1-7)需要放入每层的值;
5.注意:标记问题:同一数可以重复使用
组合问题:i 从上一层的值开始递增7结束i=a[step-1],同时注意a[0]边界
回溯问题:sum+=i; dfs(step+1); sum-=i; 等价于 dfs(sum+i,step+1)
因为这一层的sum没有改变;
#include<stdio.h> int a[101],n; void dfs(int sum,int step) { int i; if(sum>n)return ; //加的过程sum可能直接大于7,设置出口; if(sum==n) //终止条件的设置; { for(i=1;i<=step-2;i++) //(情况1)最后step为n+1,所有要想打印前6个数,应为step-2 printf("%d+",a[i]); printf("%d\n",a[step-1]); //最后一层分开打印,因为前面为%d+,最后一个数为%d\n; return ; //结束跳出函数; } for(i=a[step-1];i<n;i++) //i从上一层的值开始,组合问题,后一层总比前一层大; { //同时注意边界问题i=a[step-1]; a[step]=i; dfs(sum+i,step+1); //系统自动回溯; } } int main() { scanf("%d",&n); //需要拆分的数字,如n=7; a[0]=1; //使当step==1时a[step-1]成立,i若等于0,sum永远=0,死局; dfs(0,1); return 0; }
刷题网站总结
问题 C: [USACO 1.1.1]你要乘坐的飞碟在这里 - OJ (jsuacm.cn)http://jsuacm.cn/problem.php?cid=1684&pid=2
1.UFO
一个众所周知的事实,在每一慧星后面是一个不明飞行物UFO。 这些不明飞行物时常来收集来自在地球上忠诚的支持者。 不幸地,他们的空间在每次旅行只能带上一群支持者。 他们要做的是用一种聪明的方案让每一个团体人被慧星带走。 他们为每个慧星起了一个名字,通过这些名字来决定一个团体是不是特定的慧星带走。 那个相配方案的细节在下面被给出; 你的工作要写一个程序来通过团体的名字和彗星的名字来决定一个组是否应该与在那一颗慧星后面的不明飞行物搭配。团体的名字和慧星的名字都以下列各项方式转换成一个数字: 这个最后的数字代表名字中所有字母的信息,"A" 是 1 和 "Z" 是 26。举例来说,团体 "USACO" 会是 21*19*1*3*15=17955 。 如果团体的数字 mod 47 等于慧星的数字 mod 47,那么你要告诉这个团体准备好被带走 ! 写一个程序读入慧星的名字和团体的名字,如果搭配打印"GO"否者打印"STAY" 团体的名字和慧星的名字将会是没有空格或标点的一串大写字母(不超过6个字母)
样例输入 复制
COMETQ
HVNGAT样例输出 复制
GO
#include<stdio.h> #include<string.h> int main() { char s1[7],s2[7]; int i=0,sum1=1,sum2=1,a,b; gets(s1); gets(s2); a=strlen(s1); b=strlen(s2); for(i=0;i<a;i++) { sum1=sum1*(s1[i]-64)%47; //字符直接引用计算 } for(i=0;i<b;i++) { sum2=sum2*(s2[i]-64)%47; } if(sum1==sum2)printf("GO"); else printf("STAY"); }
问题 G: 密码(JSU-ZJJ) - OJ (jsuacm.cn)http://jsuacm.cn/problem.php?cid=1684&pid=62.密码
网上流传一句话:"常在网上飘啊,哪能不挨刀啊~"。其实要想能安安心心地上网其实也不难,学点安全知识就可以。
一般来说一个比较安全的密码至少应该满足下面两个条件:
(1).密码长度大于等于8,且不要超过16。
(2).密码中的字符应该来自下面“字符类别”中四组中的至少三组。
这四个字符类别分别为:
1.大写字母:A,B,C...Z;
2.小写字母:a,b,c...z;
3.数字:0,1,2...9;
4.特殊符号:~,!,@,#,$,%,^,&;
给你一个密码,你的任务就是判断它是不是一个安全的密码。输入
输入数据第一行包含一个数M,接下有M行,每行一个密码(长度最大可能为50),密码仅包括上面的四类字符。
输出
对于每个测试实例,判断这个密码是不是一个安全的密码,是的话输出YES,否则输出NO。
样例输入 复制
3 a1b2c3d4 Linle@ACM ^~^@^@!%
样例输出 复制
NO YES NO
#include<stdio.h> #include<string.h> int main() { int n; scanf("%d",&n); getchar(); while(n--) { char a[51]; int i,p=0,q=0,x=0,y=0,k; gets(a); k=strlen(a); if(k<8||k>16) { printf("NO\n"); continue; //情况分类,continue:跳出循环 } else { for(i=0; i<k; i++) { if(a[i]<='z'&&a[i]>='a')p=1; else if(a[i]<='Z'&&a[i]>='A')q=1; else if(a[i]>='0'&&a[i]<='9')y=1; else if(a[i]=='~'||a[i]=='!'||a[i]=='@'||a[i]=='#'||a[i]=='$'||a[i]=='%'||a[i]=='^'||a[i]=='&')x=1; } if((x+y+p+q)>=3) printf("YES\n"); else printf("NO\n"); } } return 0; }
问题 J: 字符串操作一(串) - OJ (jsuacm.cn)http://jsuacm.cn/problem.php?cid=1684&pid=9
3.字符串的翻转
输入一长度为n的字符串,若其n为偶数,则将字符串从中间反转,若为奇数,则将前后各(n-1)/2个字符反转,中间字符不动。
输入
输入有多组,每行有一个字符串
输出
对应每行输出反转后的字符串
样例输入 复制
asdfghjkl qwerty
样例输出 复制
fdsaglkjh ewqytr
#include <stdio.h> int main() { char s[100],t; //字符串长度不分奇偶,操作一样; int i,j,n; //根据题意,分为前半段和后半段处理即可; while(~scanf("%s",s)) { n=strlen(s); for(i=0,j=n/2-1; i<j; i++,j--) //i<j循环条件的设置; { t=s[i]; s[i]=s[j]; s[j]=t; } for(i=n/2+n%2,j=n-1; i<j; i++,j--) //i的起点(边界点)的设置; { t=s[i]; s[i]=s[j]; s[j]=t; } puts(s); } }