1315:【例4.5】集合的划分
【题目描述】
【题目分析】
【代码实现】
#include<bits/stdc++.h>
using namespace std;
long long f(int n, int k) {
if (n < k || k == 0 || n == 0)return 0;
if (n == k || k == 1)return 1;
return f(n - 1, k - 1) + f(n - 1, k) * k;
}
int main() {
int n, k;
cin >> n >> k;
cout << f(n, k);
return 0;
}
1316:【例4.6】数的计数(Noip2001)
【题目描述】
我们要求找出具有下列性质数的个数(包括输入的自然数n)。先输入一个自然数n(n≤1000),然后对此自然数按照如下方法进行处理:
不作任何处理;
在它的左边加上一个自然数,但该自然数不能超过原数的一半;
加上数后,继续按此规则进行处理,直到不能再加自然数为止。
【题目分析】
【代码实现】
#include<bits/stdc++.h>
using namespace std;
long long ans = 1;
long long a[10000];
/*记忆化递归*/
long long dfs(int n) {
if (a[n] != 0) return a[n];
else {
a[n]++;
for (int i = 1; i <= n / 2; i++) {
a[n] += dfs(i);
}
return a[n];
}
}
int main() {
int n;
cin >> n;
a[1] = 0;
a[2] = 2;
cout << dfs(n);
return 0;
}
1198:逆波兰表达式
【题目描述】
逆波兰表达式是一种把运算符前置的算术表达式,例如普通的表达式2 + 3的逆波兰表示法为+ 2 3。逆波兰表达式的优点是运算符之间不必有优先级关系,也不必用括号改变运算次序,例如(2 + 3) * 4的逆波兰表示法为* + 2 3 4。本题求解逆波兰表达式的值,其中运算符包括+ - * /四个。
【题目分析】
【代码实现】
#include<bits/stdc++.h>
using namespace std;
char a[105];
double calc() {
cin >> a;
switch (a[0]) {
case '+':
return calc() + calc();
break;
case '-':
return calc() - calc();
break;
case '*':
return calc() * calc();
break;
case '/':
return calc() / calc();
break;
default:
return atof(a);
break;
}
}
int main() {
printf("%f\n", calc());
return 0;
}
1199:全排列
【题目描述】
给定一个由不同的小写字母组成的字符串,输出这个字符串的所有全排列。
我们假设对于小写字母有‘a’ <‘b’ < ... <‘y’<‘z’,而且给定的字符串中的字母已经按照从小到大的顺序排列。
【题目分析】
【代码实现】
#include<stdio.h>
#include<iostream>
#include<cstring>
using namespace std;
char a[15];
char b[15];
bool vis[15];
int len = 0;
void dfs(int n) {
for (int i = 0; i < len; i++) {
if (vis[i]) continue;
b[n] = a[i];
if (n == len) {
for (int j = 1; j <= len; j++) printf("%c", b[j]);
printf("\n");
return;
} else {
vis[i] = 1;
dfs(n + 1);
vis[i] = 0;
}
}
}
int main() {
cin >> a;
len = strlen(a);
dfs(1);
return 0;
}
1200:分解因数
【题目描述】
给出一个正整数a,要求分解成若干个正整数的乘积,即a=a1×a2×a3×...×an,并且1<a1≤a2≤a3≤...≤an,问这样的分解的种数有多少。注意到a=a也是一种分解。
【题目分析】
【代码实现】
#include<bits/stdc++.h>
using namespace std;
#define N 10010
int ans = 0;
int a[N]; //记录数据的内容
int b[N]; //记录数据的访问状态
int n = 0;
void print() {
for (int i = 1; i <= n; i++)cout << a[i] << " ";
ans++;
cout << endl;
}
void f(int t) {
for (int i = 1; i <= n; i++) {
if (!b[i]) { //该数据没有使用过
a[t] = i;
b[i] = 1;
if (t == n) print();
else f(t + 1);
b[i] = 0;
}
}
}
int main() {
cin >> n;
// for(int i=1;i<=n;i++)cin>>a[i];//读入数据
f(1);
cout << ans;
return 0;
}
1201:菲波那契数列
【题目描述】
菲波那契数列是指这样的数列: 数列的第一个和第二个数都为1,接下来每个数都等于前面2个数之和。给出一个正整数a,要求菲波那契数列中第a个数是多少。
【题目分析】
【代码实现】
#include<bits/stdc++.h>
using namespace std;
int a[25]={0,1,1};
int f(int t){
if(a[t]!=0) return a[t];
return a[t]=f(t-1)+f(t-2);;
}
int main(){
int n,t;
// cout<<f(3);
for(int i=1;i<=24;i++) cout<<f(i)<<" ";
// cin>>n;
// for(int i=1;i<=n;i++){
// cin>>t;
// cout<<f(t)<<endl;
// }
return 0;
}
1202:Pell数列
【题目描述】
Pell数列a1,a2,a3,...的定义是这样的,a1=1,a2=2,...,an=2*an−1+an−2(n>2)
给出一个正整数 k,要求Pell数列的第 k项模上 32767是多少。
【题目分析】
【代码实现】
#include<bits/stdc++.h>
using namespace std;
int a[1000010] = {0, 1, 2};
int pell(int x) {
if (a[x] != 0) return a[x];
return a[x] = (2 * pell(x - 1) + pell(x - 2)) % 32767;
}
int main() {
for (int i = 1; i <= 1000000; i++) pell(i);
int n, t;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> t;
cout << a[t] << endl;
}
return 0;
}
1203:扩号匹配问题
【题目描述】
在某个字符串(长度不超过100)中有左括号、右括号和大小写字母;规定(与常见的算数式子一样)任何一个左括号都从内到外与在它右边且距离最近的右括号匹配。写一个程序,找到无法匹配的左括号和右括号,输出原来字符串,并在下一行标出不能匹配的括号。不能匹配的左括号用"$"标注,不能匹配的右括号用"?"标注。
【题目分析】
【代码实现】
#include<bits/stdc++.h>
using namespace std;
char a[105];
int left1[105],right1[105];
int len,l,r;
void f(int p){
if(p==len) return;
if(a[p]=='(') left1[l++]=p;
if(a[p]==')'){
if(l>0)l--;
else right1[r++]=p;
}
a[p]=' ';
f(p+1);
}
int main(){
while(cin>>a){
cout<<a<<endl;
len=strlen(a);
l=r=0;
f(0);
for(int i=0;i<l;i++){
a[left1[i]]='$';
}
for(int i=0;i<r;i++){
a[right1[i]]='?';
}
for(int i=0;i<len;i++) cout<<a[i];
cout<<endl;
}
return 0;
}
1204:爬楼梯
【题目描述】
树老师爬楼梯,他可以每次走1级或者2级,输入楼梯的级数,求不同的走法数。例如:楼梯一共有3级,他可以每次都走一级,或者第一次走一级,第二次走两级,也可以第一次走两级,第二次走一级,一共3种方法
【题目分析】
【代码实现】
#include<bits/stdc++.h>
using namespace std;
int resolve(int n){
if(n==1) return 1;
if(n==2) return 2;
return resolve(n-1)+resolve(n-2);
}
int main(){
int n;
while(cin>>n){
cout<<resolve(n)<<endl;
}
return 0;
}
1205:汉诺塔问题
【题目描述】
约19世纪末,在欧州的商店中出售一种智力玩具,在一块铜板上有三根杆,最左边的杆上自上而下、由小到大顺序串着由64个圆盘构成的塔。目的是将最左边杆上的盘全部移到中间的杆上,条件是一次只能移动一个盘,且不允许大盘放在小盘的上面。
这是一个著名的问题,几乎所有的教材上都有这个问题。由于条件是一次只能移动一个盘,且不允许大盘放在小盘上面,所以64个盘的移动次数是:18,446,744,073,709,551,615
这是一个天文数字,若每一微秒可能计算(并不输出)一次移动,那么也需要几乎一百万年。我们仅能找出问题的解决方法并解决较小N值时的汉诺塔,但很难用计算机解决64层的汉诺塔。
假定圆盘从小到大编号为1, 2, ...
【题目分析】
【代码实现】
#include<bits/stdc++.h>
using namespace std;
void f(int n,char a, char b,char c){
if(n==0) return;
f(n-1,a,c,b);
printf("%c->%d->%c\n",a,n,b);
// cout<<a<<"->"<<n<<"->"<<b<<endl;
f(n-1,c,b,a);
}
int main(){
int n;
char a,b,c;
cin>>n>>a>>b>>c;
f(n,a,b,c);
return 0;
}
1206:放苹果
【题目描述】
把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法。
【题目分析】
【代码实现】
#include <bits/stdc++.h>
using namespace std;
int f(int m, int n) {
if ( n == 1 || m == 1 || m == 0) return 1;
if (m < n) return f(m, m);
return f(m, n - 1) + f(m - n, n);
}
int main() {
//input data
int t;
cin >> t;
while (t--) {
int m, n;
cin >> m >> n;
cout << f(m, n) << endl;
}
return 0;
}
1207:求最大公约数问题
【题目描述】
给定两个正整数,求它们的最大公约数。
【题目分析】
【代码实现】
#include <bits/stdc++.h>
using namespace std;
int gcd(int m, int n) {
if (n == 0) return m;
else return gcd(n, m % n);
}
int main() {
//input data
int m, n;
cin >> m >> n;
cout << gcd(m, n);
return 0;
}
1208:2的幂次方表示
【题目描述】
【题目分析】
【代码实现】
#include <bits/stdc++.h>
using namespace std;
void f(int n, int k) {
if (n == 1) {
if (k == 1) printf("2");
else if(k==0||k==2) printf("2(%d)", k);
else {
printf("2(");
f(k,0);
printf(")");
}
return;
}
f(n / 2, k + 1);
if (n % 2 == 1) {
if (k == 1) printf("+2");
else if(k==0||k==2) printf("+2(%d)", k);
else {
printf("+2(");
f(k,0);
printf(")");
}
}
}
int main() {
//input data
int n;
cin >> n;
f(n, 0);
return 0;
}
1209:分数求和
【题目描述】
【题目分析】
【代码实现】
#include <bits/stdc++.h>
using namespace std;
int gcd(int m, int n) {
if (n == 0) return m;
else return gcd(n, m%n);
}
int main() {
//input data
int k, n, m, a, b;
char c;
cin >> k;
k--;
cin >> m >> c >> n;
while (k--) {
cin >> a >> c >> b;
int mm = a * n + b * m;
int nn = n * b;
int kk = gcd(mm, nn);
m = mm / kk, n = nn / kk;
}
if (n == 1) cout << m;
else
cout << m << "/" << n;
return 0;
}
1210:因子分解
【题目描述】
输入一个数,输出其素因子分解表达式。
【题目分析】
【代码实现】
#include <bits/stdc++.h>
using namespace std;
int a[25] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97};
void f(int n, int m, int sum) {
if (n == 1) {
if (sum == 1) cout << a[m] ;
if (sum > 1) cout << a[m] << "^" << sum;
return ;
}
if (n % a[m] == 0) {
sum++;
f(n / a[m], m, sum);
} else {
if (sum == 1) cout << a[m] << "*";
if (sum > 1) cout << a[m] << "^" << sum << "*";
f(n, m + 1, 0);
}
}
int main() {
//input data
int n;
cin >> n;
f(n, 0, 0);
return 0;
}
1211:判断元素是否存在
【题目描述】
有一个集合M是这样生成的:(1) 已知k是集合M的元素; (2) 如果y是M的元素,那么,2y+1和3y+1都是M的元素;(3) 除了上述二种情况外,没有别的数能够成为M的一个元素。
问题:任意给定k和x,请判断x是否是M的元素。这里的k是无符号整数,x 不大于 100000,如果是,则输出YES,否则,输出NO。
【题目分析】
【代码实现】
#include<bits/stdc++.h>
using namespace std;
bool check(int k, int x) {
if (x == k)return true;
if (x > k) return check(2 * k + 1, x) || check(3 * k + 1, x);
if (x < k) return false;
}
int main() {
int x, k;
scanf("%d,%d", &k, &x);
if (check(k, x)) cout << "YES";
else cout << "NO";
return 0;
}