题目感觉比较模式,中规中矩,但是很容易超时或者是有些复杂情况覆盖不到
进制转换
题目描述
将一个长度最多为30位数字的十进制非负整数转换为二进制数输出。
输入描述:
多组数据,每行为一个长度不超过30位的十进制非负整数。
(注意是10进制数字的个数可能有30个,而非30bits的整数)
输出描述:
每行输出对应的二进制数。
示例1
输入
复制
0
1
3
8
输出
复制
0
1
11
1000
数字长度过长,long long 类型也无法存储,使用字符串存储
#include<iostream>
#include<stdio.h>
#include<string>
using namespace std;
string div2(string input){
// cout<<"div:"<<input<<endl;
int rmd=0;
int shang=0;
string res;
for(int i=0;i<input.size();i++){
shang=(rmd*10+input[i]-'0')/2;
res.push_back(shang+'0');
rmd=(rmd*10+input[i]-'0')%2;
}
while(res.size()>0){
if(res[0]=='0')
res.erase(res.begin());
else
break;
}
// cout<<"div2"<<endl;
if(res.size()==0){
return "0";
}
return res;
}
char rmd2(string input){
// cout<<"rmd:"<<input<<endl;
if((input[input.size()-1]-'0')%2==0){
return '0';
}
else{
return '1';
}
}
string getres(string input){
// cout<<"getres:"<<input<<endl;
string res;
char rmd;
while(input!="0"){
rmd=rmd2(input);
input=div2(input);
res.insert(res.begin(),rmd);
}
if(res.size()==0)
return "0";
return res;
}
int main(){
string input;
while(cin>>input){
cout<<getres(input)<<endl;
}
}
成绩排序
查找和排序
题目:输入任意(用户,成绩)序列,可以获得成绩从高到低或从低到高的排列,相同成绩
都按先录入排列在前的规则处理。
示例:
jack 70
peter 96
Tom 70
smith 67
从高到低 成绩
peter 96
jack 70
Tom 70
smith 67
从低到高
smith 67
jack 70
Tom 70
peter 96
输入描述:
输入多行,先输入要排序的人的个数,然后输入排序方法0(降序)或者1(升序)再分别输入他们的名字和成绩,以一个空格隔开
输出描述:
按照指定方式输出名字和成绩,名字和成绩之间以一个空格隔开
示例1
输入
复制
3
0
fang 90
yang 50
ning 70
输出
复制
fang 90
ning 70
yang 50
排序,结构体定义,重载操作符,注意审题
#include<vector>
#include<algorithm>
using namespace std;
struct record{
string name;
int score;
int count;
int asc;
bool operator < (const record& r) const{
if(score!=r.score)
return score<r.score;
else{
if(asc==0)
return count>r.count;
else
return count<r.count;
}
}
};
int main(){
int n,asc;
int count;
while(cin>>n){
count=0;
cin>>asc;
vector<record> re;
while(n--){
record temp;
cin>>temp.name;
cin>>temp.score;
temp.count=count;
temp.asc=asc;
re.push_back(temp);
count++;
}
sort(re.begin(),re.begin()+re.size());
if(asc==1){
for(int i=0;i<re.size();i++){
cout<<re[i].name<<" "<<re[i].score<<endl;
}
}
else if(asc==0){
for(int i=re.size()-1;i>=0;i--){
cout<<re[i].name<<" "<<re[i].score<<endl;
}
}
}
}
约数的个数
输入n个整数,依次输出每个数的约数的个数
输入描述:
输入的第一行为N,即数组的个数(N<=1000)
接下来的1行包括N个整数,其中每个数的范围为(1<=Num<=1000000000)
当N=0时输入结束。
输出描述:
可能有多组输入数据,对于每组输入数据,
输出N行,其中每一行对应上面的一个数的约数的个数。
示例1
输入
复制
5
1 3 4 6 12
输出
复制
1
2
3
4
6
数的范围很大,直接暴力会超时,转化为开方
#include<iostream>
using namespace std;
int main(){
int n;
int tmp;
while(cin>>n){
while(n--){
cin>>tmp;
int sum=0;
int i;
for(i=1;i*i<tmp;i++){
if(tmp%i==0)
sum+=2;
}
if(i*i==tmp)
sum++;
cout<<sum<<endl;
}
}
}
代理服务器
题目描述
使用代理服务器能够在一定程度上隐藏客户端信息,从而保护用户在互联网上的隐私。我们知道n个代理服务器的IP地址,现在要用它们去访问m个服务器。这 m 个服务器的 IP 地址和访问顺序也已经给出。系统在同一时刻只能使用一个代理服务器,并要求不能用代理服务器去访问和它 IP地址相同的服务器(不然客户端信息很有可能就会被泄露)。在这样的条件下,找到一种使用代理服务器的方案,使得代理服务器切换的次数尽可能得少。
输入描述:
每个测试数据包括 n + m + 2 行。
第 1 行只包含一个整数 n,表示代理服务器的个数。
第 2行至第n + 1行每行是一个字符串,表示代理服务器的 IP地址。这n个 IP地址两两不相同。
第 n + 2 行只包含一个整数 m,表示要访问的服务器的个数。
第 n + 3 行至第 n + m + 2 行每行是一个字符串,表示要访问的服务器的 IP 地址,按照访问的顺序给出。
每个字符串都是合法的IP地址,形式为“xxx.yyy.zzz.www”,其中任何一部分均是0–255之间的整数。输入数据的任何一行都不包含空格字符。
其中,1<=n<=1000,1<=m<=5000。
输出描述:
可能有多组测试数据,对于每组输入数据, 输出数据只有一行,包含一个整数s,表示按照要求访问服务器的过程中切换代理服务器的最少次数。第一次使用的代理服务器不计入切换次数中。若没有符合要求的安排方式,则输出-1。
示例1
输入
复制
3
166.111.4.100
162.105.131.113
202.112.128.69
6
72.14.235.104
166.111.4.100
207.46.19.190
202.112.128.69
162.105.131.113
118.214.226.52
输出
复制
1
动态规划思想
#include<iostream>
#include<vector>
using namespace std;
int main(){
int n;
int MAX=6000;
while(cin>>n){
vector<string> agent(n);
for(int i=0;i<n;i++){
cin>>agent[i];
}
int m;
cin>>m;
vector<string> server(m);
for(int i=0;i<m;i++){
cin>>server[i];
}
vector<vector<int> > dis(m+1);
for(int i=0;i<m+1;i++){
dis[i].resize(n);
for(int j=0;j<n;j++){
dis[i][j]=MAX;
}
}
for(int i=m-1;i>=0;i--){
for(int j=0;j<n;j++){
if(server[i]==agent[j]){
dis[i][j]=0;
}
else{
dis[i][j]=dis[i+1][j]+1;
}
}
}
int count=0;
int index=0;
int jndex=0;
int max=0;
for(int i=0;i<n;i++){
if(max<dis[0][i]){
index=i;
max=dis[0][i];
}
}
if(max==0){
cout<<"-1"<<endl;
break;
}
jndex=jndex+dis[0][index];
while(jndex<m){
max=0;
index=0;
for(int i=0;i<n;i++){
if(max<dis[jndex][i]){
index=i;
max=dis[jndex][i];
}
}
if(max==0){
count=-1;
break;
}
jndex=jndex+dis[jndex][index];
count++;
}
cout<<count<<endl;
}
}
手机键盘
题目描述
按照手机键盘输入字母的方式,计算所花费的时间 如:a,b,c都在“1”键上,输入a只需要按一次,输入c需要连续按三次。 如果连续两个字符不在同一个按键上,则可直接按,如:ad需要按两下,kz需要按6下 如果连续两字符在同一个按键上,则两个按键之间需要等一段时间,如ac,在按了a之后,需要等一会儿才能按c。 现在假设每按一次需要花费一个时间段,等待时间需要花费两个时间段。 现在给出一串字符,需要计算出它所需要花费的时间。
输入描述:
一个长度不大于100的字符串,其中只有手机按键上有的小写字母
输出描述:
输入可能包括多组数据,对于每组数据,输出按出Input所给字符串所需要的时间
示例1
输入
复制
bob
www
输出
复制
7
7
能记起九宫格是什么样就行了
#include<iostream>
#include<vector>
using namespace std;
int main(){
vector<int>pos(26);
vector<int>time(26);
pos[0]=2;
time[0]=1;
pos[1]=2;
time[1]=2;
pos[2]=2;
time[2]=3;
pos[3]=3;
time[3]=1;
pos[4]=3;
time[4]=2;
pos[5]=3;
time[5]=3;
pos[6]=4;
time[6]=1;
pos[7]=4;
time[7]=2;
pos[8]=4;
time[8]=3;
pos[9]=5;
time[9]=1;
pos[10]=5;
time[10]=2;
pos[11]=5;
time[11]=3;
pos[12]=6;
time[12]=1;
pos[13]=6;
time[13]=2;
pos[14]=6;
time[14]=3;
pos[15]=7;
time[15]=1;
pos[16]=7;
time[16]=2;
pos[17]=7;
time[17]=3;
pos[18]=7;
time[18]=4;
pos[19]=8;
time[19]=1;
pos[20]=8;
time[20]=2;
pos[21]=8;
time[21]=3;
pos[22]=9;
time[22]=1;
pos[23]=9;
time[23]=2;
pos[24]=9;
time[24]=3;
pos[25]=9;
time[25]=4;
string s;
while(cin>>s){
int res=0;
int pre=-1;
for(int i=0;i<s.size();i++){
int ii=s[i]-'a';
res+=time[ii];
if(pos[ii]==pre) res+=2;
pre=pos[ii];
}
cout<<res<<endl;
}
}
整数拆分1
题目描述
一个整数总可以拆分为2的幂的和,例如: 7=1+2+4 7=1+2+2+2 7=1+1+1+4 7=1+1+1+2+2 7=1+1+1+1+1+2 7=1+1+1+1+1+1+1 总共有六种不同的拆分方式。 再比如:4可以拆分成:4 = 4,4 = 1 + 1 + 1 + 1,4 = 2 + 2,4=1+1+2。 用f(n)表示n的不同拆分的种数,例如f(7)=6. 要求编写程序,读入n(不超过1000000),输出f(n)%1000000000。
输入描述:
每组输入包括一个整数:N(1<=N<=1000000)。
输出描述:
对于每组数据,输出f(n)%1000000000。
示例1
输入
复制
7
输出
复制
6
题目的意思是将整数n拆分成2的幂,一共有多少种拆分方法,思路为动态规划,那么关键就是递归方程如何写!!
考虑以下情况
- n为奇数时,可以拆分的情况之后在n-1的拆分情况上加1,即 f(n)=f(n-1)
- n为偶数时,对n进行拆分,按照可不可以拆分出1划分
- 可以拆分出1,f(n-1)
- 不可以拆分出1,也就是将n/2拆分的结果每个乘2,即f(n/2)
- f(n)=f(n-1)+f(n/2)
- 起始为 f(0)=0,f(1)=1,f(2)=2
#include<stdio.h>
int main(){
int dp[1000001],num,i;
dp[0]=0;
dp[1]=1;
dp[2]=2;
for(i=3;i<=1000000;i++){
dp[i]=0;
if(i&1)
dp[i]=(dp[i-1])%1000000000;
else
dp[i]=(dp[i-1]+dp[i/2])%1000000000;
}
while(scanf("%d",&num)!=EOF)
printf("%d\n",dp[num]);
}
关于数组分配的空间是不是太大这个问题很玄学
数字拆分2
这道题为看到的另一个经典的动态规划题目
输入n,k;输出将n拆分为最大值为k的组合的个数
如n=5,k=5时输出结果为5
思路如下
- 当n=k时,f(n,k)=f(n,k-1)+1。加的1时n=k
- 当n<k时,f(n,k)=f(n,n)
- 当n>k时,考虑能不能拆分出k
- f(n,k)=f(n-k,k)+f(n,k-1)
- 初始条件为 f(1,i)=1,f(i,1)=1
#include<stdio.h>
#include<iostream>
#include<vector>
using namespace std;
int main(){
int n,k;
while(cin>>n){
cin>>k;
vector<vector <int> > dp(n+1);
for(int i=0;i<=n;i++){
dp[i].resize(k+1);
for(int j=0;j<=k;j++){
dp[i][j]=0;
if(j==1) dp[i][j]=1;
if(i==1) dp[i][j]=1;
}
}
for(int i=2;i<=n;i++){
for(int j=2;j<=k;j++){
if(i==j) dp[i][j]=dp[i][j-1]+1;
else if(i<j) dp[i][j]=dp[i][i];
else{
dp[i][j]=dp[i-j][j]+dp[i][j-1];
}
}
}
}
}
二叉树遍历
题目描述
编一个程序,读入用户输入的一串先序遍历字符串,根据此字符串建立一个二叉树(以指针方式存储)。 例如如下的先序遍历字符串: ABC##DE#G##F### 其中“#”表示的是空格,空格字符代表空树。建立起此二叉树以后,再对二叉树进行中序遍历,输出遍历结果。
输入描述:
输入包括1行字符串,长度不超过100。
输出描述:
可能有多组测试数据,对于每组数据,
输出将输入字符串建立二叉树后中序遍历的序列,每个字符后面都有一个空格。
每个输出结果占一行。
示例1
输入
复制
abc##de#g##f###
输出
复制
c b e g d f a
根据先序遍历还原二叉树,之后进行中序遍历
因为先序遍历的时候是从根节点开始一直向左下遍历,那么就按照这个顺序构造二叉树,设置全局变量并且传参时使用引用将读取先序遍历的每种情况,如果读到#说明为叶子节点,之后不再添加,使用build函数返回node*
#include<stdio.h>
#include<iostream>
using namespace std;
struct Node{
char val;
Node *lchild;
Node *rchild;
};
Node* build(int &index,string s){
index++;
Node * root=new Node();
char c=s[index];
if(c=='#'){
return NULL;
}
else{
root->val=c;
root->lchild=build(index,s);
root->rchild=build(index,s);
return root;
}
}
void inorder(Node *root){
if(root==NULL) return;
inorder(root->lchild);
cout<<root->val<<" ";
inorder(root->rchild);
}
int main(){
string s;
while(cin>>s){
int index=-1;
Node* root;
root=build(index,s);
inorder(root);
cout<<endl;
}
}
玛雅人的密码
玛雅人有一种密码,如果字符串中出现连续的2012四个数字就能解开密码。给一个长度为N的字符串,(2=<N<=13)该字符串中只含有0,1,2三种数字,问这个字符串要移位几次才能解开密码,每次只能移动相邻的两个数字。例如02120经过一次移位,可以得到20120,01220,02210,02102,其中20120符合要求,因此输出为1.如果无论移位多少次都解不开密码,输出-1。
输入描述:
输入包含多组测试数据,每组测试数据由两行组成。
第一行为一个整数N,代表字符串的长度(2<=N<=13)。
第二行为一个仅由0、1、2组成的,长度为N的字符串。
输出描述:
对于每组测试数据,若可以解出密码,输出最少的移位次数;否则输出-1。
示例1
输入
复制
5
02120
输出
复制
1
对题目简单分析之后是搜索问题,如果用深度优先搜索实现困难,没想到具体要怎么实现,由于又是要求最优解,所以使用广度优先搜索对结果进行搜索,状态为移位的次数。另外,存储已经被扩展过的字符串,如果再次出现不再扩展,剪枝。
判断是否是包含字符串使用有限状态机。
#include<iostream>
#include<stdio.h>
#include<queue>
#include<map>
using namespace std;
//广度优先搜索吗
struct R{
string s;
int change=0; //交换的次数
};
bool ispass(R r){
int state=0;
for(int i=0;i<r.s.size();i++){
switch(state){
case 0:
if(r.s[i]=='2')
state=1;
break;
case 1:
if(r.s[i]=='0')
state=2;
else
state=0;
break;
case 2:
if(r.s[i]=='1')
state=3;
else
state=0;
break;
case 3:
if(r.s[i]=='2')
return true;
else
state=0;
break;
}
}
return false;
}
int main(){
int n;
while(cin>>n){
queue<R> que;
map<string,int> exist;
R r;
int res=1001;
cin>>r.s;
int count1=0;
int count0=0;
int count2=0;
for(int i=0;i<r.s.size();i++){
if(r.s[i]=='0')
count0++;
else if(r.s[i]=='1')
count1++;
else if(r.s[i]=='2')
count2++;
}
if(count1<1||count0<1||count2<2){
cout<<"-1"<<endl;
continue;
}
que.push(r);
if(ispass(r)){
cout<<"0"<<endl;
continue;
}
while(!que.empty()){
R tmp2;
tmp2=que.front();
que.pop();
for(int i=0;i<tmp2.s.size()-1;i++){
string tmp3;
for(int j=0;j<tmp2.s.size();j++)
tmp3.push_back(tmp2.s[j]);
char tmp4=tmp3[i];
tmp3[i]=tmp3[i+1];
tmp3[i+1]=tmp4;
if(exist.find(tmp3)==exist.end()){
// cout<<tmp3<<endl;
exist[tmp3]=1;
R tmp5;
tmp5.s=tmp3;
tmp5.change=tmp2.change+1;
if(ispass(tmp5)){
res=min(res,tmp5.change);
}
else{
que.push(tmp5);
}
}
}
}
if(res>1000){
cout<<"-1"<<endl;
}
else{
cout<<res<<endl;
}
}
}
最小邮票数
题目描述
有若干张邮票,要求从中选取最少的邮票张数凑成一个给定的总值。 如,有1分,3分,3分,3分,4分五张邮票,要求凑成10分,则使用3张邮票:3分、3分、4分即可。
输入描述:
有多组数据,对于每组数据,首先是要求凑成的邮票总值M,M<100。然后是一个数N,N〈20,表示有N张邮票。接下来是N个正整数,分别表示这N张邮票的面值,且以升序排列。
输出描述:
对于每组数据,能够凑成总值M的最少邮票张数。若无解,输出0。
示例1
输入
复制
10
5
1 3 3 3 4
输出
复制
3
要求正好装满的01背包问题
#include<iostream>
#include<vector>
using namespace std;
int main(){
int m,n; //邮票总价值,邮票的数量
while(cin>>m){
cin>>n;
vector<int> stamp(n);
for(int i=0;i<n;i++)
cin>>stamp[i];
vector<int> dp(m+1,100001);
dp[0]=0;
// cout<<"1:"<<endl;
for(int i=0;i<n;i++){
for(int j=m;j>=stamp[i];j--){
dp[j]=min(dp[j],dp[j-stamp[i]]+1);
}
}
if(dp[m]==100001)
cout<<"0"<<endl;
else
cout<<dp[m]<<endl;
}
}
abc
题目描述
设a、b、c均是0到9之间的数字,abc、bcc是两个三位数,且有:abc+bcc=532。求满足条件的所有a、b、c的值。
输入描述:
题目没有任何输入。
输出描述:
请输出所有满足题目条件的a、b、c的值。
a、b、c之间用空格隔开。
每个输出占一行。
#include<iostream>
using namespace std;
int main(){
for(int a=0;a<10;a++){
for(int b=0;b<10;b++){
for(int c=0;c<10;c++){
if(100*a+110*b+12*c==532){
cout<<a<<" "<<b<<" "<<c<<endl;
}
}
}
}
}
root(N,k)
题目描述
N<k时,root(N,k) = N,否则,root(N,k) = root(N',k)。N'为N的k进制表示的各位数字之和。输入x,y,k,输出root(x^y,k)的值 (这里^为乘方,不是异或),2=<k<=16,0<x,y<2000000000,有一半的测试点里 x^y 会溢出int的范围(>=2000000000)
输入描述:
每组测试数据包括一行,x(0<x<2000000000), y(0<y<2000000000), k(2<=k<=16)
输出描述:
输入可能有多组数据,对于每一组数据,root(x^y, k)的值
示例1
输入
复制
4 4 10
输出
复制
4
快速幂除法:求a^b%c 时对a和b分别降低,另外由于即使知道了大整数除法不会溢出的方法,也不能快速求出答案,所以对关系式进行推导
#include<iostream>
#include<math.h>
using namespace std;
long long root(long long x,long long y,long long k){
long long res=1;
// x=x%k;
while(y){
if(y&1) res=(res*x)%k;
x=(x*x)%k;
y=y>>1;
}
return res;
}
int main(){
long long x,y,k,res;
while(cin>>x){
cin>>y;
cin>>k;
res=root(x,y,k-1);
if(res==0) cout<<k-1<<endl;
else cout<<res<<endl;
}
}
n的阶乘
特殊乘法
题目描述
写个算法,对2个小于1000000000的输入,求结果。 特殊乘法举例:123 * 45 = 1*4 +1*5 +2*4 +2*5 +3*4+3*5
输入描述:
两个小于1000000000的数
输出描述:
输入可能有多组数据,对于每一组数据,输出Input中的两个数按照题目要求的方法进行运算后得到的结果。
示例1
输入
复制
123 45
输出
复制
54
#include<iostream>
#include<vector>
using namespace std;
int main(){
string a,b;
while(cin>>a){
cin>>b;
vector<int> aa;
vector<int> bb;
for(int i=0;i<a.size();i++){
aa.push_back(a[i]-'0');
}
for(int i=0;i<b.size();i++){
bb.push_back(b[i]-'0');
}
int res=0;
for(int i=0;i<aa.size();i++){
for(int j=0;j<bb.size();j++){
res+=aa[i]*bb[j];
}
}
cout<<res<<endl;
}
}
今年的第几天
题目描述
输入年、月、日,计算该天是本年的第几天。
输入描述:
包括三个整数年(1<=Y<=3000)、月(1<=M<=12)、日(1<=D<=31)。
输出描述:
输入可能有多组测试数据,对于每一组测试数据,
输出一个整数,代表Input中的年、月、日对应本年的第几天。
示例1
输入
复制
1990 9 20
2000 5 1
输出
复制
263
122
#include<iostream>
using namespace std;
bool isrun(int year){
if((year%4==0&&year%100!=0)||(year%400)==0) return true;
else return false;
}
int main(){
int days[12][2]={
{31,31},
{28,29},
{31,31},
{30,30},
{31,31},
{30,30},
{31,31},
{31,31},
{30,30},
{31,31},
{30,30},
{31,31},
};
int year,month,day;
while(cin>>year){
cin>>month;
cin>>day;
int index=0;
if(isrun(year)) index=1;
int res=0;
for(int i=0;i<month-1;i++){
// cout<<"add:"<<days[index][i]<<endl;
res+=days[i][index];
}
res+=day;
cout<<res<<endl;
}
}
完数vs盈数
题目描述
一个数如果恰好等于它的各因子(该数本身除外)子和,如:6=3+2+1。则称其为“完数”;若因子之和大于该数,则称其为“盈数”。 求出2到60之间所有“完数”和“盈数”。
输入描述:
题目没有任何输入。
输出描述:
输出2到60之间所有“完数”和“盈数”,并以如下形式输出:
E: e1 e2 e3 ......(ei为完数)
G: g1 g2 g3 ......(gi为盈数)
其中两个数之间要有空格,行尾不加空格。
#include<iostream>
#include<vector>
using namespace std;
int main(){
vector<int> E; //完数
vector<int> G; //盈数
for(int i=2;i<=60;i++){
int tmp=0;
for(int j=1;j<i;j++){
if(i%j==0) tmp+=j;
}
if(tmp==i) E.push_back(i);
else if(tmp>i) G.push_back(i);
}
cout<<"E:";
for(int i=0;i<E.size();i++){
cout<<" "<<E[i];
}
cout<<endl;
cout<<"G:";
for(int i=0;i<G.size();i++){
cout<<" "<<G[i];
}
cout<<endl;
}
最大序列和
题目描述
给出一个整数序列S,其中有N个数,定义其中一个非空连续子序列T中所有数的和为T的“序列和”。 对于S的所有非空连续子序列T,求最大的序列和。 变量条件:N为正整数,N≤1000000,结果序列和在范围(-2^63,2^63-1)以内。
输入描述:
第一行为一个正整数N,第二行为N个整数,表示序列中的数。
输出描述:
输入可能包括多组数据,对于每一组输入数据,
仅输出一个数,表示最大序列和。
示例1
输入
复制
5
1 5 -3 2 4
6
1 -2 3 4 -10 6
4
-3 -1 -2 -5
输出
复制
9
7
-1
#include<iostream>
using namespace std;
int main(){
int n;
while(cin>>n){
int tmp;
cin>>tmp;
int cur=tmp;
int maxx=tmp;
n--;
while(n--){
cin>>tmp;
if(cur+tmp>tmp){
cur=cur+tmp;
}
else{
cur=tmp;
}
maxx=max(cur,maxx);
}
cout<<maxx<<endl;
}
}
最小花费
题目描述
在某条线路上有N个火车站,有三种距离的路程,L1,L2,L3,对应的价格为C1,C2,C3.其对应关系如下: 距离s 票价 0<S<=L1 C1 L1<S<=L2 C2 L2<S<=L3 C3 输入保证0<L1<L2<L3<10^9,0<C1<C2<C3<10^9。 每两个站之间的距离不超过L3。 当乘客要移动的两个站的距离大于L3的时候,可以选择从中间一个站下车,然后买票再上车,所以乘客整个过程中至少会买两张票。 现在给你一个 L1,L2,L3,C1,C2,C3。然后是A B的值,其分别为乘客旅程的起始站和终点站。 然后输入N,N为该线路上的总的火车站数目,然后输入N-1个整数,分别代表从该线路上的第一个站,到第2个站,第3个站,……,第N个站的距离。 根据输入,输出乘客从A到B站的最小花费。
输入描述:
以如下格式输入数据:
L1 L2 L3 C1 C2 C3
A B
N
a[2]
a[3]
……
a[N]
输出描述:
可能有多组测试数据,对于每一组数据,
根据输入,输出乘客从A到B站的最小花费。
示例1
输入
复制
1 2 3 1 2 3
1 2
2
2
输出
复制
2
动态规划,和建广告牌那个题差不多
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
struct LC{
int l;
int c;
bool operator < (const LC &lc) const{
if(c/l==lc.c/lc.l) return c<lc.c;
else return c/l<lc.c/lc.l;
}
};
int main(){
int tmp,a,b,n;
while(cin>>tmp){
// LC lc[3];
vector<LC> lc(3);
lc[0].l=tmp;
cin>>lc[1].l;
cin>>lc[2].l;
cin>>lc[0].c;
cin>>lc[1].c;
cin>>lc[2].c;
sort(lc.begin(),lc.begin()+lc.size());
cin>>a;
cin>>b;
cin>>n;
vector<int> dis(n+1);
vector<int> res(n+1);
for(int i=0;i<=n;i++){
res[i]=1000000000;
}
res[a]=0;
for(int i=2;i<=n;i++){
cin>>dis[i];
}
dis[1]=0;
for(int i=a+1;i<=b;i++){ //到达每一个站的最小花费
for(int j=a;j<i;j++){
int distance=dis[i]-dis[j];
// cout<<"dis:"<<distance<<endl;
for(int k=0;k<lc.size();k++){
if(lc[k].l>=distance){
res[i]=min(res[i],res[j]+lc[k].c);
}
}
}
}
cout<<res[b]<<endl;
}
}
N的阶乘
题目描述
输入一个正整数N,输出N的阶乘。
输入描述:
正整数N(0<=N<=1000)
输出描述:
输入可能包括多组数据,对于每一组输入数据,输出N的阶乘
示例1
输入
复制
4
5
15
输出
复制
24
120
1307674368000
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
string add(string a,string b){
string res;
int car=0;
int lena=a.size();
int lenb=b.size();
int len=min(lena,lenb);
int ai,bi;
for(ai=lena-1,bi=lenb-1;len>0;len--,ai--,bi--){
int aa=a[ai]-'0';
int bb=b[bi]-'0';
int tmp=(aa+bb+car)%10;
car=(aa+bb+car)/10;
res.insert(res.begin(),tmp+'0');
}
if(lena==lenb){
if(car!=0){
res.insert(res.begin(),car+'0');
}
return res;
}
else if(lena<lenb){
for(int i=bi;i>=0;i--){
int tmp=((b[i]-'0')+car)%10;
car=((b[i]-'0')+car)/10;
res.insert(res.begin(),tmp+'0');
}
if(car!=0){
res.insert(res.begin(),car+'0');
}
return res;
}
else if(lenb<lena){
for(int i=ai;i>=0;i--){
int tmp=((a[i]-'0')+car)%10;
car=((a[i]-'0')+car)/10;
res.insert(res.begin(),tmp+'0');
}
if(car!=0){
res.insert(res.begin(),car+'0');
}
return res;
}
}
string mul(string a,string b){
string res="0";
if(a=="0"||b=="0") return res;
int lena=a.size();
int lenb=b.size();
int zero=0;
for(int bi=lenb-1;bi>=0;bi--){
int car=0;
string rest;
for(int ai=lena-1;ai>=0;ai--){
int aa=a[ai]-'0';
int bb=b[bi]-'0';
int tmp=aa*bb+car;
rest.insert(rest.begin(),tmp%10+'0');
car=tmp/10;
}
if(car!=0) rest.insert(rest.begin(),car+'0');
for(int i=0;i<zero;i++){
rest.push_back('0');
}
zero++;
res=add(res,rest);
}
return res;
}
/*
string to_string2(int n){
if(n==0) return "0";
else{
string res;
while(n!=0){
res.insert(res.begin(),n%10+'0');
n=n/10;
}
return res;
}
}*/
string jiecheng(int n){
if(n==0) return "1";
string res=to_string(n);
for(int i=n-1;i>0;i--){
res=mul(res,to_string(i));
}
return res;
}
int main(){
int a;
while(cin>>a){
cout<<jiecheng(a)<<endl;
}
}
剩下的树
题目描述
有一个长度为整数L(1<=L<=10000)的马路,可以想象成数轴上长度为L的一个线段,起点是坐标原点,在每个整数坐标点有一棵树,即在0,1,2,...,L共L+1个位置上有L+1棵树。 现在要移走一些树,移走的树的区间用一对数字表示,如 100 200表示移走从100到200之间(包括端点)所有的树。 可能有M(1<=M<=100)个区间,区间之间可能有重叠。现在要求移走所有区间的树之后剩下的树的个数。
输入描述:
两个整数L(1<=L<=10000)和M(1<=M<=100)。
接下来有M组整数,每组有一对数字。
输出描述:
可能有多组输入数据,对于每组输入数据,输出一个数,表示移走所有区间的树之后剩下的树的个数。
示例1
输入
复制
500 3
100 200
150 300
470 471
输出
复制
298
10进制vs2进制
题目描述
对于一个十进制数A,将A转换为二进制数,然后按位逆序排列,再转换为十进制数B,我们乘B为A的二进制逆序数。 例如对于十进制数173,它的二进制形式为10101101,逆序排列得到10110101,其十进制数为181,181即为173的二进制逆序数。
输入描述:
一个1000位(即10^999)以内的十进制数。
输出描述:
输入的十进制数的二进制逆序数。
示例1
输入
复制
173
输出
复制
181
查找学生信息
题目描述
输入N个学生的信息,然后进行查询。
输入描述:
输入的第一行为N,即学生的个数(N<=1000)
接下来的N行包括N个学生的信息,信息格式如下:
01 李江 男 21
02 刘唐 男 23
03 张军 男 19
04 王娜 女 19
然后输入一个M(M<=10000),接下来会有M行,代表M次查询,每行输入一个学号,格式如下:
02
03
01
04
输出描述:
输出M行,每行包括一个对应于查询的学生的信息。
如果没有对应的学生信息,则输出“No Answer!”
示例1
输入
复制
4
01 李江 男 21
02 刘唐 男 23
03 张军 男 19
04 王娜 女 19
5
02
03
01
04
03
输出
复制
02 刘唐 男 23
03 张军 男 19
01 李江 男 21
04 王娜 女 19
03 张军 男 19
函数求值
题目描述
给定正整数N,函数F(N)表示小于等于N的自然数中1和2的个数之和,例如:1,2,3,4,5,6,7,8,9,10序列中1和2的个数之和为3,因此 F(10)=3。输入N,求F(N)的值,1=<N<=10^100(10的100次方)若F(N)很大,则求F(N)mod20123的值
输入描述:
无
输出描述:
无
示例1
输入
复制
10
10
输出
复制
3
3
#include<iostream>
using namespace std;
int main(){
string str;
while(cin>>str){
int len=str.length();
int result=0,count=0,num=0;
for(int i=0;i<len;i++){
int temp=str[i]-'0';
result=((result-count)*10+num*2+count*(temp+1)+min(temp,2))%20123;
num=(num*10+temp)%20123;
if(temp==1||temp==2){
++count;
}
}
cout<<result<<endl;
}
return 0;
}
参考内容:https://blog.youkuaiyun.com/qq_38341682/article/details/88647619
对数据进行找规律,从F(1),F(12),F(123),F(1234)逐渐递推
F(123)中1,2的个数为result,count为123中1,2的个数,num为123,也就是1234之间间隔了多少个10,temp为最后一位的数
(result-count)*10 表示122x中1,2的个数,不包括各位
num*2 表示122x中个位上1,2的个数
count*(temp+1)表示123x中1,2的个数,不包括个位
min(temp,2)表示123x中个位上1,2的个数
进制转化2
题目描述
将M进制的数X转换为N进制的数输出。
输入描述:
输入的第一行包括两个整数:M和N(2<=M,N<=36)。
下面的一行输入一个数X,X是M进制的数,现在要求你将M进制的数X转换成N进制的数输出。
输出描述:
输出X的N进制表示的数。
示例1
输入
复制
10 2
11
输出
复制
1011
备注:
注意输入时如有字母,则字母为大写,输出时如有字母,则字母为小写。
#include<iostream>
using namespace std;
int main(){
int m,n;
string x;
while(cin>>m){
cin>>n;
cin>>x;
long long tmp=0;
int cur=0;
for(int i=0;i<x.length();i++){
if(x[i]>='0'&&x[i]<='9'){
cur=x[i]-'0';
}
else if(x[i]<='Z'&&x[i]>='A'){
cur=10+x[i]-'A';
}
tmp=tmp*m+cur;
}
// cout<<"temp:"<<tmp<<endl;
string res;
int rmd=0;
while(tmp!=0){
rmd=tmp%n;
if(rmd<10){
res.insert(res.begin(),rmd+'0');
tmp=tmp/n;
}
else{
res.insert(res.begin(),rmd-10+'a');
tmp=tmp/n;
}
}
cout<<res<<endl;
}
}
反序数
题目描述
设N是一个四位数,它的9倍恰好是其反序数(例如:1234的反序数是4321)
求N的值
输入描述:
程序无任何输入数据。
输出描述:
输出题目要求的四位数,如果结果有多组,则每组结果之间以回车隔开。
示例1
输入
复制
无
输出
复制
无
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
string a,b;
for(int i=1000;i<1112;i++){
a=to_string(i);
b=to_string(i*9);
if(b.length()!=4) continue;
reverse(b.begin(),b.end());
bool flag=true;
for(int i=0;i<a.length();i++){
if(a[i]!=b[i]){
flag=false;
break;
}
}
if(flag){
cout<<a<<endl;
}
}
}
完全平方数
题目描述
打印所有不超过256,其平方具有对称性质的数。如2,11就是这样的数,因为2*2=4,11*11=121。
输入描述:
无任何输入数据
输出描述:
输出具有题目要求的性质的数。如果输出数据不止一组,各组数据之间以回车隔开。
示例1
输入
复制
无
输出
复制
无
#include<iostream>
using namespace std;
int main(){
for(int i=0;i<=256;i++){
string a=to_string(i*i);
int begin=0;
int end=a.size()-1;
bool flag=true;
while(begin<=end){
if(a[begin]==a[end]){
begin++;
end--;
}
else{
flag=false;
break;
}
}
if(flag){
cout<<i<<endl;
}
}
}