p1112 取数问题
题目
描述 Description
我们来玩一个游戏:自然数1到N,按顺序列成一排,你可以从中取走任意个数,但是相邻的两个不可以同时被取走。如果你能算出一共有多少种取法,那么你会被天神Liushiji奖励。
输入格式 Input Format
一个数n(1< n < 50)。
输出格式 Output Format
仅包含一个数——你的答案。
样例输入 Sample Input
5
样例输出 Sample Output
13
时间限制 Time Limitation
1s
代码
#include<iostream>
using namespace std;
long long n,MAX;
long long F[1110];
long long f(int n)
{
if(F[n]!=0) return F[n];
if(n==1) return F[n]=2;
if(n==2) return F[n]=3;
return F[n]=f(n-1)+f(n-2);
}
int main()
{
cin>>n;
f(n);
cout <<f(n)<<endl;
return 0;
}
p1113 2的幂次方
题目
描述 Description
任何一个正整数都可以用2的幂次方表示。例如:
137=27+23+2^0
同时约定方次用括号来表示,即ab 可表示为a(b)。
由此可知,137可表示为:
2(7)+2(3)+2(0)
进一步:7= 22+2+20 (21用2表示)
3=2+2^0
所以最后137可表示为:
2(2(2)+2+2(0))+2(2+2(0))+2(0)
又如:
1315=2^10 +2^8 +2^5 +2+2^0
所以1315最后可表示为:
2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)
输入:正整数(n≤20000)
输出:符合约定的n的0,2表示(在表示中不能有空格)
输入格式 Input Format
一个正整数
输出格式 Output Format
符合约定的n的0,2表示(在表示中不能有空格)
样例输入 Sample Input
73
样例输出 Sample Output
2(2(2)+2)+2(2+2(0))+2(0)
时间限制 Time Limitation
1s
代码
#include<bits/stdc++.h>
#include<cstdio>
using namespace std;
void power(int n)
{
if(n==1)
{
printf("2(0)");
return;
}
if(n==2)
{
printf("2");
return;
}
int p=1,s=0;
while(p<=n)
{
p*=2;
s++;
}
s=s-1;
if(n==p/2)
{
printf("2(");
power(s);
printf(")");
}else
{
if(p/2==2)
{
printf("2");
printf("+");
power(n-p/2);
}
else
{
printf("2(");
power(s);
printf(")+");
power(n-p/2);
}
}
}
int main()
{
int n;
scanf("%d",&n);
power(n);
}
p1114 拍卖
题目
描述 Description
一般情况下,拍卖行的拍卖师在拍卖商品的时候都是从低价开始起拍,由买方报价,最后谁出的价格高,商品就归谁所有。但焦作有个拍卖行,拍卖师在拍卖商品时正好相反:总是从高价开始起拍,如果没有人举成交牌就降价,而且拍卖师在降价时还有规律:假如第i次报价为w元,那么第i+1次报价为w-a或者w-b元,如果降到p元时,你认为价格合适,赶快第一个举成交牌,你就花p元买下了商品。
任务:拍卖师把商品从w元降到p元的方法总数。
输入格式 Input Format
文件第一行有两个正整w 和p ,第二行有有两个正整a 和b.
1 ≤ w,p ≤ 10^6 , 2 ≤ a,b ≤ 10000, a不等于b.
输出格式 Output Format
文件只有一行,即所求得的方法总数。注意:测试数据中方法总数不超过MAXlongint.
样例输入 Sample Input
10 3
2 3
样例输出 Sample Output
3
时间限制 Time Limitation
1s
代码
#include<bits/stdc++.h>
using namespace std;
long long F[1000020];
int w,p,a,b,ans;
int d(int t)
{
if(F[t]>=0) return F[t];
if(t==p) return 1;
if(t<p) return 0;
F[t]=d(t-a)+d(t-b);
return (F[t]);
}
int main()
{
cin>>w>>p>>a>>b;
ans=0;
memset(F,-1,sizeof(F));
F[p]=1;
cout<<d(w);
return 0;
}
p1115 集合划分问题
题目
描述 Description
n 个元素的集合{1,2,., n }可以划分为若干个非空子集。例如,当n=4 时,集合{1,2, 3,4}可以划分为15 个不同的非空子集如下:
{{1},{2},{3},{4}},
{{1,2},{3},{4}},
{{1,3},{2},{4}},
{{1,4},{2},{3}},
{{2,3},{1},{4}},
{{2,4},{1},{3}},
{{3,4},{1},{2}},
{{1,2},{3,4}},
{{1,3},{2,4}},
{{1,4},{2,3}},
{{1,2,3},{4}},
{{1,2,4},{3}},
{{1,3,4},{2}},
{{2,3,4},{1}},
{{1,2,3,4}}
其中,集合{{1,2,3,4}} 由1 个子集组成;集合{{1,2},{3,4}},{{1,3},{2, 4}},{{1,4},{2,3}},{{1,2,3},{4}},{{1,2,4},{3}},{{1,3,4},{2}},{{2, 3,4},{1}} 由2 个子集组成;集合{{1,2},{3},{4}},{{1,3},{2},{4}},{{1,4}, {2},{3}},{{2,3},{1},{4}},{{2,4},{1},{3}},{{3,4},{1},{2}} 由3 个子集组成;集合{{1},{2},{3},{4}} 由4 个子集组成。
编程任务:
给定正整数n 和m,计算出n 个元素的集合{1,2,., n }可以划分为多少个不同的由m 个非空子集组成的集合。
输入格式 Input Format
第1 行是元素个数n 和非空子集数m。
0<m<n<=60
输出格式 Output Format
将计算出的不同的非空子集数输出.
样例输入 Sample Input
4 3
样例输出 Sample Output
6
时间限制 Time Limitation
1s
注释 Hint
递归公式,
设n个元素的集合可以划分为F(n,m)个不同的由m个非空子集组成的集合。
F(n,m) = 1, when n=0, n=m, n=1, or m=1
F(n,m) = 0, when n<m
否则
F(n,m)=F(n-1,m-1)+m*F(n-1,m)
例如:
考虑3个元素的集合,可划分为
① 1个子集的集合:{{1,2,3}}
② 2个子集的集合:{{1,2},{3}},{{1,3},{2}},{{2,3},{1}}
③ 3个子集的集合:{{1},{2},{3}}
∴F(3,1)=1;F(3,2)=3;F(3,3)=1;
如果要求F(4,2)该怎么办呢?
A.往①里添一个元素{4},得到{{1,2,3},{4}}
B.往②里的任意一个子集添一个4,得到
{{1,2,4},{3}},{{1,2},{3,4}},
{{1,3,4},{2}},{{1,3},{2,4}},
{{2,3,4},{1}},{{2,3},{1,4}}
∴F(4,2)=F(3,1)+2F(3,2)=1+23=7
来源 Source
经典题目
代码
#include<bits/stdc++.h>
using namespace std;
int n,m;
long long dfs(int n,int m)
{
if(n==0||n==m||n==1||m==1) return 1;
if(n<m) return 0;
return dfs(n-1,m-1)+dfs(n-1,m)*m;
}
int main()
{
cin>>n>>m;
dfs(n,m);
cout<<dfs(n,m);
return 0;
}
p1116 超级书架
题目
描述 Description
Farmer John最近为奶牛们的图书馆添置了一个巨大的书架,尽管它是如此
的大,但它还是几乎瞬间就被各种各样的书塞满了。现在,只有书架的顶上还留
有一点空间。
所有N(1 <= N <= 20)头奶牛都有一个确定的身高H_i(1 <= H_i <= 1,000,000 - 好高的奶牛>_<)。设所有奶牛身高的和为S。书架的高度为B,并且保证1 <= B <= S。
为了够到比最高的那头奶牛还要高的书架顶,奶牛们不得不象演杂技一般,一头站在另一头的背上,叠成一座“奶牛塔”。当然,这个塔的高度,就是塔中所有奶牛的身高之和。为了往书架顶上放东西,所有奶牛的身高和必须不小于书架的高度。
塔叠得越高便越不稳定,于是奶牛们希望找到一种方案,使得叠出的塔在高
度不小于书架高度的情况下,高度尽可能小。你也可以猜到你的任务了:写一个
程序,计算奶牛们叠成的塔在满足要求的情况下,最少要比书架高多少。
输入格式 Input Format
* 第1行: 2个用空格隔开的整数:N 和 B
- 第2…N+1行: 第i+1行是1个整数:H_i
输出格式 Output Format- 第1行: 输出1个非负整数,即奶牛们叠成的塔最少比书架高的高度
样例输入 Sample Input
- 第1行: 输出1个非负整数,即奶牛们叠成的塔最少比书架高的高度
5 16
3
1
3
5
6
样例输出 Sample Output
1
时间限制 Time Limitation
1s
注释 Hint
输出说明:
我们选用奶牛1、3、4、5叠成塔,她们的总高度为3 + 3 + 5 + 6 = 17。任何方案都无法叠出高度为16的塔,于是答案为1。
代码
#include<bits/stdc++.h>
using namespace std;
int sum,n,b;
const int MAXN=100000+10;
int f[MAXN],h[MAXN];
int main()
{
cin>>n>>b;
for(int i=1;i<=n;i++) cin>>h[i];
sort(h+1,h+n+1);
for(int i=1;i<=n;i++) sum+=h[i];
int k=sum-b;
for(int i=1;i<=n;i++)
{
for(int j=k;j>=h[i];j--)
f[j]=max(f[j],f[j-h[i]]+h[i]);
}
cout<<k-f[k];
return 0;
}
p1117 倒牛奶(Milk3)
题目
描述 Description
农民约翰有三个容量分别是A,B,C升的桶,A,B,C分别是三个从1到20的整数,
最初,A和B桶都是空的,而C桶是装满牛奶的。有时,约翰把牛奶从一个桶倒到另一个桶中,直到被灌桶装满或原桶空了。当然每一次灌注都是完全的。由于节约,牛奶不会有丢失。
写一个程序去帮助约翰找出当A桶是空的时候,C桶中牛奶所剩量的所有可能性。
输入格式 Input Format
单独的一行包括三个整数A,B和C。
输出格式 Output Format
只有一行,升序地列出当A桶是空的时候,C桶牛奶所剩量的所有可能性。
样例输入 Sample Input
SAMPLE INPUT 1
8 9 10
SAMPLE INPUT 2
2 5 10
样例输出 Sample Output
SAMPLE OUTPUT 1
1 2 8 9 10
SAMPLE OUTPUT 2
5 6 7 8 9 10
时间限制 Time Limitation
1s
代码
#include<bits/stdc++.h>
using namespace std;
int A,B,C,t=0;
const int MAX=25;
int num1[MAX][MAX][MAX];
int num[MAX],sum[120000]={0};
void f(int a,int b,int c)
{
if(num1[a][b][c]==0)
{
if(a==0) sum[++t]=c;
num1[a][b][c]=1;
if(c>=A-a) f(A,b,c-A+a); else f(a+c,b,0);
if(c>=B-b) f(a,B,c-B+b); else f(a,b+c,0);
if(a>=C-c) f(a-C+c,b,C); else f(0,b,c+a);
if(a>=B-b) f(a-B+b,B,c); else f(0,b+a,c);
if(b>=C-c) f(a,b-C+c,C); else f(a,0,b+c);
if(b>=A-a) f(A,b-A+a,c); else f(a+b,0,c);
}
else return;
}
int main()
{
cin>>A>>B>>C;
memset(num1,0,sizeof(num1));
f(0,0,C);
sort(sum+1,sum+t+1);
for(int i=1;i<=t;i++)
cout<<sum[i]<<' ';
cout<<endl;
return 0;
}