算法作业一。
问题 A: 小雏鸟的成人式 2
题目描述
陶行知先生说:“我们要活的书,不要死的书 ”。
小雏鸟们从书上都是对的到现在能去伪存真的去使用书籍,证明你们长大了。总之就是要有自己的主见,自己的思考。
大白希望大家都能拿到一百分,所以对100这个数以及他的倍数很喜欢。
大白发现,从1开始,一定能找出一个序列从小到大排列,使得每一项都是 恰好能且仅能 被100整除D次。
请你编写程序,找到这个数列里第N个数。
输入
多行。每行输入两个整数,表示D和N,N范围[1,100],D范围[0,2]
输出
每行对应输入,给出一个符合题意的整数
样例输入
0 5
1 11
2 85
样例输出
5
1100
850000
提示
代码
#include<iostream>
#include<cmath>
using namespace std;
int main()
{
int d,n;
while(cin>>d>>n)
{
if(n>=1&&n<100&&d>=0&&d<=2)
cout<<n*int(pow(100,d))<<endl;
else if(n==100)
cout<<101*int(pow(100,d))<<endl;
else
continue;
}
}
问题 B: 小雏鸟的成人式 3
题目描述
陶行知先生说:“因为道德是做人的根本。根本一坏,纵然使你有一些学问和本领,也无甚用处。”
小雏鸟们需要时刻铭记在心,不管你长成什么样的的攻城狮,都必须三观正确。
涛涛轰这一天带着爱美酱来到了一个风景如画的地方游玩。艳阳高照,他俩玩的很尽兴,但是现在他们口渴了。
涛涛轰:“我要买饮料!”
店主:“我们这里有三种饮料,矿泉水1.5元一瓶,可乐2元一瓶,橙汁3.5元一瓶。”
涛涛轰:“好的,给我一瓶矿泉水。”
说完他掏出一张N元的大钞递给店主。
店主:“我忘了提醒你了,我们这里没有找客人钱的习惯的,多的钱我们都当小费收了的,嘿嘿。”
涛涛轰:“……”
涛涛轰环顾四周,就这一家商店,况且实在太渴了,看着脸热的粉扑扑的一头汗的爱美酱,就决定在这买了。不过涛涛轰想,与其把钱当小费送给他还不如自己多买一点饮料,反正早晚都要喝,但是要尽量少让他赚小费。
现在涛涛轰希望你能帮他计算一下,最少他要给店主多少小费。
输入
输入数据的第一行是一个整数T(1<=T<=100),代表测试数据的数量。然后是T行测试数据,每个测试数据只包含一个正整数N(1<=N<=10000),N代表小明手中钞票的面值,以分为单位。
注意:商店里只有题中描述的三种饮料。
输出
对于每组测试数据,请你输出小明最少要浪费多少钱给店主作为小费,以分为单位。
样例输入
2
900
250
样例输出
0
50
提示
代码
#include<iostream>
#include<cmath>
using namespace std;
void test(int x)
{
if(x<150)
cout<<x<<endl;
else if(x<=200||x>300)
cout<<(x%50)<<endl;
else
cout<<x-200<<endl;
}
int main()
{
int n,x;
cin>>n;
while(n--)
{
cin>>x;
test(x);
}
}
问题 C: 大白just大白
题目描述
大家都知道,大白对学术要求是很严格的。抄作业、考试作弊神马的在大白这简直不能忍。
这不刚刚过去的期末考试。有n个学生被查出来有问题。
大白给了他们申辩的机会,每个学生可以提交一段文字,作为申辩理由。但是大白发现来的人总会有一些奇怪的理由。
大白提前列了m个常见借口关键字。他想看看来申辩的学生中最烂的申辩理由是什么。
所谓最烂申辩理由就是,申辩里,含有常见借口关键字最多的。
含有关键字,指的是,理由中出现了一串和关键字完全匹配的字符串,如果出现大写小写不同,也认为匹配。比如,关键字是 bed 理由中出现Bedroom算含有一个关键字。
输入
一个输入可能有多个case,每个case第一行两个数。分别代表n 和 m
接下来m行,每行一个关键字(字符串)
再接下来n行字符串。m和n都不大于20
每一个借口和借口关键字只会包含大小写字母,长度不会超过4000个字符。
输出
对于每个case输出一行字符串,表示最烂的理由。若有多个理由包含相同数目的关键字,按输入顺序输出靠前的那个。
样例输入
2 3
love
cumt
ACM
ILoveCUMTACM
cumtAACM
2 2
A
b
Ab
bA
样例输出
ILoveCUMTACM
Ab
提示
代码
#include<iostream>
#include<string>
#include<string.h>
#include <algorithm>
using std::string;
using namespace std;
bool search(string str,string sub)
{
int i;
if((i = str.find(sub, i)) != std::string::npos)
return true;
else
return false;
}
int main()
{
int m,n,k=0,local=0;
while(cin>>n>>m)
{
string key[m],ca[n],key1[m],ca1[n];
for(int i=0;i<m;i++)
{
cin>>key[i];
key1[i]=key[i];
transform(key1[i].begin(),key1[i].end(),key1[i].begin(),::tolower);
}
for(int i=0;i<n;i++)
{
cin>>ca[i];
ca1[i]=ca[i];
transform(ca1[i].begin(),ca1[i].end(),ca1[i].begin(),::tolower);
}
for(int i=0;i<n;i++)
{
int num=0;
for(int j=0;j<m;j++)
{
if(search(ca1[i],key1[j]))
num++;
//cout<<search(ca1[i],key1[j])<<endl;
}
if(num>k)
{
k=num;
local=i;
}
}
//cout<<local<<endl;
//cout<<k<<endl;
cout<<ca[local]<<endl;
}
}
问题 D: 小雏鸟的计算
题目描述
小雏鸟们的三角形翅膀终于长出健壮的肌肉和丰满的羽毛,已经跃跃欲试的去准备尝试挑战新的难题了。
考虑以下的算法:
\1. 输入 n
\2. 印出 n
\3. 如果 n = 1 结束
\4. 如果 n 是奇数 那么 n=3*n+1
\5. 否则 n=n/2
\6. GOTO 2
例如输入 22 得到的数列: 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1
据推测此算法对任何整数而言会终止 (当打印出 1 的时候)。虽然此算法很简单,但以上的推测是否真实却无法知道。然而对所有的n ( 0 < n < 1000000 )来说,以上的推测已经被验证是正确的。
给一个输入 n 透过以上的算法我们可以得到一个数列(1作为结尾)。此数列的长度称为n的cycle length。上面提到的例子 22的 cycle length为 16.
问题来了:对任2个整数i,j我们想要知道介于i,j(包含i,j)之间的数所产生的数列中最大的cycle length是多少。
输入
输入可能包含了好几行测试数据,每一行有一对整数 i,j 。
0< i,j < 1000000
输出
对每一对输入 i j你应该要输出 i j和介于i j之间的数所产生的数列中最大的cycle length。
样例输入
1 10
10 1
100 200
201 210
900 1000
样例输出
1 10 20
10 1 20
100 200 125
201 210 89
900 1000 174
提示
代码
#include<iostream>
using namespace std;
int test(int n)
{
int count=0;
while(n!=1)
{
count++;
if(n%2!=0)
n=3*n+1;
else
n=n/2;
}
count++;
return count;
}
int main()
{
int i,j;
while(cin>>i>>j)
{
cout<<i<<" "<<j<<" ";
int max=0;
if(i>j)
{
int m;
m=i;
i=j;
j=m;
}
for(int k=i;k<=j;k++)
{
if(test(k)>max)
max=test(k);
}
cout<<max<<endl;
}
}
问题 E: 进制转换
题目描述
输入一个十进制正整数,然后输出它所对应的八进制数。
输入
输入一个十进制正整数n(1≤n≤106) 。
输出
输出n对应的八进制数,输出在一行。
样例输入
10
样例输出
12
提示
代码
#include<iostream>
#include<stack>
using namespace std;
void transform(int x)
{
stack <int> stk;
while(x!=0)
{
stk.push(x%8);
x=x/8;
}
while(!stk.empty())
{
cout<<stk.top();
stk.pop();
}
cout<<endl;
}
int main()
{
int n;
cin>>n;
transform(n);
}
问题 F: 排列问题
题目描述
输入一个可能含有重复字符的字符串,打印出该字符串中所有字符的全排列。
输入
单组测试数据,输入数据是一个长度不超过10个字符的字符串,以逗号结尾。
输出
打印出该字符串中所有字符的全排列。以字典序顺序输出,用空格分隔。
样例输入
abc,
样例输出
abc acb bac bca cab cba
提示
代码
#include<iostream>
#include<cstdio>
#include<string>
#include<map>
#include<algorithm>
using namespace std;
int main()
{
string str;
cin >> str;
str = str.substr(0, str.length() - 1);
sort(str.begin(),str.end());
do
{
cout << str <<" ";
}while(next_permutation(str.begin(),str.end()));
return 0;
}
问题 G: 快速幂
题目描述
输入
多组测试样例,最多50组。每组测试样例给定一个整数x(1<=x<=25000)
输出
对每个样例,输出一行,代表f(x)对100000007取余的结果。
样例输入
3
4
5
样例输出
33
289
3414
提示
代码
#include<iostream>
#include<cmath>
using namespace std;
long long n=100000007;
long long poww(long long a, long long b) {
long long ans = 1;
while (b)
{
if (b & 1 != 0)
ans=ans*a%n;
a=a*a%n;
b >>= 1;
}
return ans;
}
int main()
{
long long n=100000007;
int x;
while(cin>>x)
{
long long sum=0;
for(int i=1;i<=x;i++)
{
sum+=(poww(i,i));
}
cout<<(sum+1)%n<<endl;
}
return 0;
}
问题 H: 求第k小
题目描述
给定n(1<=n<=1000000)个元素,求第k小数(1<=k<=n)。
输入
一组样例。第一行输入两个整数n和k。第二行输入n个不同的int范围内的数。
输出
输出一行,输出第k小数。
样例输入
5 2
1 5 3 2 4
样例输出
2
提示
代码
#include<iostream>
#include<algorithm>
using namespace std;
int a[1000010];
int main()
{
int n,k;
cin>>n>>k;
for(int i=0;i<n;i++)
{
cin>>a[i];
}
sort(a,a+n);
cout<<a[k-1]<<endl;
}
问题 I: 沙子的质量
题目描述
设有N堆沙子排成一排,其编号为1,2,3,…,N(N< =300)。每堆沙子有一定的数量,可以用一个整数来描述,现在要将N堆沙子合并成为一堆,每次只能合并相邻的两堆,合并的代价为这两堆沙子的数量之和,合并后与这两堆沙子相邻的沙子将和新堆相邻,合并时由于选择的顺序不同,合并的总代价也不相同,如有4堆沙子分别为1 3 5 2我们可以先合并1、2堆,代价为4,得到4 5 2又合并1,2堆,代价为9,得到9 2,再合并得到11,总代价为4+9+11=24,如果第二步是先合并2,3堆,则代价为7,得到4 7,最后一次合并代价为11,总代价为4+7+11=22;问题是:找出一种合理的方法,使总的代价最小。输出最小代价。
输入
第一行一个数N表示沙子的堆数N。 第二行N个数,表示每堆沙子的质量。 a[i]< =1000。
输出
合并的最小代价。
样例输入
4
1 3 5 2
样例输出
22
提示
代码
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int n;
int num[305];
int f[305][305]; //合并a堆到b堆的最小代价
int main()
{
cin>>n;
memset(f,127/3,sizeof(f)); //初始化为一个较大值,注意memset的用法!
for(int i=1; i<=n; i++)
{
cin>>num[i];
num[i]+=num[i-1];
f[i][i]=0;
}
for(int i=2; i<=n; i++) //求1到i堆的最小代价
{
for(int j=i-1; j>=1; j--) //求j到i堆的最小代价
{
for(int k=j; k<=i; k++) //找到j到i堆的最小代价
{
f[j][i]=min(f[j][i],f[j][k]+f[k+1][i]+num[i]-num[j-1]);
}
}
}
cout<<f[1][n];
return 0;
}
问题 J: 最长公共子序列
题目描述
一个字符串A的子串被定义成从A中顺次选出若干个字符构成的串。如A=“cdaad” ,顺次选1,3,5个字符就构成子串” cad” ,现给定两个字符串,求它们的最长共公子串。
输入
第一行两个字符串用空格分开。两个串的长度均小于2000 。
输出
最长子串的长度。
样例输入
abccd aecd
样例输出
3
提示
代码
#include<iostream>
#include<string.h>
using namespace std;
int maxx(int a,int b)
{
if (a>=b) return a;
return b;
}
int main()
{
string a,b;
cin>>a>>b;
int n,m,max=0;
n=a.size();
m=b.size();
int lcm[n+1][m+1];
for(int i = 0; i <= n; ++i)
lcm[i][0] = 0;
for(int i = 0; i <= m; ++i)
lcm[0][i] = 0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(a[i-1]==b[j-1])
{
lcm[i][j]=lcm[i-1][j-1]+1;
}
else
{
lcm[i][j]=maxx(lcm[i][j-1],lcm[i-1][j]);
}
}
}
cout<<lcm[n][m];
}