问题 A: 人民币转换
题目描述
考试题目和要点:
1、中文大写金额数字前应标明“人民币”字样。中文大写金额数字应用壹、贰、叁、肆、伍、陆、柒、捌、玖、拾、佰、仟、万、亿、元、角、分、零、整等字样填写。
2、中文大写金额数字到“元”为止的,在“元”之后,应写“整字,如¥ 532.00应写成“人民币伍佰叁拾贰元整”。在”角“和”分“后面不写”整字。
3、阿拉伯数字中间有“0”时,中文大写要写“零”字,阿拉伯数字中间连续有几个“0”时,中文大写金额中间只写一个“零”字,如¥6007.14,应写成“人民币陆仟零柒元壹角肆分“。
输入
多组输入。输入一个double数。
输出
输出人民币格式。
样例输入
151121.15
样例输出
人民币拾伍万壹仟壹佰贰拾壹元壹角伍分
提示
10.56 读作人民币拾元伍角陆分
30005007 读作 三千万五千零七
30025007 读作 三千零二万五千零七
30020507 读作 三千零二万零五百零七
模拟题
位数都是4位四位的 ,个十百千,可以将数字分成很多个4位数字处理
//题目本来就比较麻烦,用字符数组处理会多很多操作,所以就用了C++的String
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=3e5+5;
const int inf=0x3f3f3f3f;
char s[maxn];
string d[7]={"","仟","佰","拾",""};
string dig[10]={"零","壹","贰","叁","肆","伍","陆","柒","捌","玖"};
int aa[100],la;
int main()
{
while(cin>>s+1){//输入的字符从1开始
int ls=strlen(s+1),la=0;
int a=0,b=0;
for(int i=1;i<=ls;++i){
if(s[i]=='.'){
for(int j=i+1;j<=ls;++j)//小数部分的值
b=b*10+s[j]-'0';
ls=i-1;
break;
}
}
for(int i=1;i<=ls;++i)//整数部分的值
a=a*10+s[i]-'0';
int _=a?1:0;//标记整数部分是否有值
while(a){//将a分成多个四位数
aa[++la]=a%10000;
a/=10000;
}
string ans="人民币";
for(int k=la;k>=1;--k){
if(aa[k]==0){//如果这部分没有数字
continue;
}
if(k<la&&(aa[k+1]%10==0||aa[k]/1000==0)){//如果前4位最后一个数为0或者当前位第一个数为0,加一个“零”
ans+=dig[0];
}
int j=1000,ju=0;//ju=0为初始,ju=1表示碰到了非0数,ju=2表示出现非0数接0的状态
for(int i=1;i<=4;++i,j/=10){
int f=(aa[k]/j)%10;
if(f){
if(ju==2)ans+=dig[0];//非0数中间有0
if(f==1&&i==3)ans+="拾";//十位为1需要特判
else ans+=dig[f]+d[i];
ju=1;
}else if(ju==1){
ju=2;
}
}
if(k==2)ans+="万";
else if(k==3)ans+="亿";
}
if(_)
ans+="元";
if(b/10)
ans+=dig[b/10]+"角";
if(b%10)
ans+=dig[b%10]+"分";
if(b==0)ans+="整";
cout<<ans<<endl;
}
return 0;
}
问题 B: 火车进站
题目描述
给定一个正整数N代表火车数量,0<N<10,接下来输入火车入站的序列,一共N辆火车,每辆火车以数字1-9编号。要求以字典序排序输出火车出站的序列号。
输入
有多组测试用例,每一组第一行输入一个正整数N(0<N<10),第二行包括N个正整数,范围为1到9。
输出
输出以字典序从小到大排序的火车出站序列号,每个编号以空格隔开,每个输出序列换行,具体见样例。
样例输入
3
1 2 3
样例输出
1 2 3
1 3 2
2 1 3
2 3 1
3 2 1
栈模拟
不过因为N只有一位也没必要用栈了,用数字就可以模拟栈
比如用数字x表示一个栈 向栈中加入数字y:x=x*10+y,出栈操作就是y=x%10,x/10
深搜所有结果,将结果排序进行输出
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e6+5;
int a[15],b[15],ans[maxn],n,cnt;
void dfs(int sta,int j,int v){//sta表示栈中的数字 j遍历要入栈的火车,v表示结果
if(sta==0&&j>n){
int x=0;
ans[++cnt]=v;
return;
}
if(j<=n) dfs(sta*10+a[j],j+1,v);//进站
if(sta) dfs(sta/10,j,v*10+sta%10);//出站
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i)scanf("%d",&a[i]);
dfs(0,1,0);//dfs深搜所有结果
sort(ans+1,ans+cnt+1);//排序
for(int i=1;i<=cnt;++i){
for(int j=n;j>=1;--j){//将数字分解成一位位的
b[j]=ans[i]%10;
ans[i]/=10;
}
for(int j=1;j<=n;++j){
printf("%d%c",b[j],j==n?'\n':' ');
}
}
return 0;
}
问题 C: DNA序列
题目描述
一个DNA序列由A/C/G/T四个字母的排列组合组成。G和C的比例(定义为GC-Ratio)是序列中G和C两个字母的总的出现次数除以总的字母数目(也就是序列长度)。在基因工程中,这个比例非常重要。因为高的GC-Ratio可能是基因的起始点。
给定一个很长的DNA序列,以及要求的最小子序列长度,研究人员经常会需要在其中找出GC-Ratio最高的子序列。
输入
输入一个字符串型基因序列和整型子串的长度。
输出
找出GC比例最高的子串,如果有多个输出第一个的子串。
样例输入
AACTGTGCACGACCTGA
5
样例输出
GCACG
提示
字符串长度<=100000
长度一定,G和C数量越多GC比例越大。问题就变成找一个长度为k的串G和C数量最多
代码1:暴力枚举每一个起点
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e6+5;
char s[maxn],ans[maxn];
int main()
{
int k,now=0,st=0,ans=0;
scanf("%s %d",s+1,&k);
int ls=strlen(s+1);
for(int i=1;i+k-1<=ls;++i){
int num=0;
for(int j=i;j<=i+k-1;++j){
if(s[j]=='C'||s[j]=='G'){
++num;
}
}
if(ans<num){
ans=num;
st=i;
}
}
for(int i=st;i<=st+k-1;++i)putchar(s[i]);
putchar('\n');
return 0;
}
代码2:前缀和优化
同样是枚举起点,不过求区间G和C的数量使用前缀计算
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e6+5;
char s[maxn],ans[maxn];
int pre[maxn];
int main()
{
int k,now=0,st=0,ans=0;
scanf("%s %d",s+1,&k);
int ls=strlen(s+1);
memset(pre,0,sizeof(pre));
for(int i=1;i<=ls;++i){
pre[i]=pre[i-1];
if(s[i]=='C'||s[i]=='G')pre[i]++;
}
for(int i=1;i+k-1<=ls;++i){
int num=pre[i+k-1]-pre[i-1];
if(ans<num){
ans=num;
st=i;
}
}
for(int i=st;i<=st+k-1;++i)putchar(s[i]);
putchar('\n');
return 0;
}
代码3:尺取法
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e6+5;
char s[maxn],ans[maxn];
int main()
{
int k,now=0,st,ans;
scanf("%s %d",s+1,&k);
int ls=strlen(s+1);
for(int i=1;i<=k;++i)//处理出第一个长度为k的串的GC
if(s[i]=='C'||s[i]=='G')++now;
ans=now,st=1;
for(int i=k+1;i<=ls;++i){//不断向右移,更新GC
if(s[i]=='C'||s[i]=='G')++now;
if(s[i-k]=='C'||s[i-k]=='G')--now;
if(now>ans){
ans=now;
st=i-k+1;
}
}
for(int i=st;i<=st+k-1;++i)putchar(s[i]);
putchar('\n');
return 0;
}
问题 D: 尼科彻斯定理
题目描述
验证尼科彻斯定理,即:任何一个整数m的立方都可以写成m个连续奇数之和。
例如:
1^3=1
2^3=3+5
3^3=7+9+11
4^3=13+15+17+19
输入
多组输入,输入一个整数。
输出
输出分解后的字符串。
样例输入
6
样例输出
31+33+35+37+39+41
从题面就可以看出规律
1^3=1 第1个奇数
2^3=3+5 第2,3个奇数
3^3=7+9+11 第4,5,6个奇数
4^3=13+15+17+19 第7,8,9,10个奇数
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+5;
const int inf=0x3f3f3f3f;
int main()
{
ll n;
while(~scanf("%lld",&n)){
ll st=(n-1)*n/2;//计算起点前面有几个奇数
st=2*st+1;//计算起点值
for(ll i=1;i<=n;++i,st+=2){//n个奇数累加
printf("%lld%c",st,i==n?'\n':'+');
}
}
return 0;
}
问题 E: 牛妹的蛋糕
题目描述
众所周知,牛妹非常喜欢吃蛋糕。
第一天牛妹吃掉蛋糕总数三分之一多一个,第二天又将剩下的蛋糕吃掉三分之一多一个,以后每天吃掉前一天剩下的三分之一多一个,到第n天准备吃的时候只剩下一个蛋糕。
牛妹想知道第一天开始吃的时候蛋糕一共有多少呢?
输入
输入n,0<n< 30。
输出
输出第一天蛋糕的数量。
样例输入
2
4
样例输出
3
10
第i天有a个蛋糕,那第i+1天有a*2/3-1
也就是说第i+1天有a个蛋糕那第i天有(a+1)*3/2个
逆向计算n次即可
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+5;
const int inf=0x3f3f3f3f;
int main()
{
int n;
while(~scanf("%d",&n)){
int ans=1;
for(int i=1;i<n;++i){
ans=3*(ans+1)/2;
}
printf("%d\n",ans);
}
return 0;
}
问题 F: 牛妹的礼物
题目描述
众所周知,牛妹有很多很多粉丝,粉丝送了很多很多礼物给牛妹,牛妹的礼物摆满了地板。
地板是N×M 的格子,每个格子有且只有一个礼物,牛妹已知每个礼物的体积。
地板的坐标是左上角(1,1) 右下角(N, M)。
牛妹只想要从屋子左上角走到右下角,每次走一步,每步只能向下走一步或者向右走一步或者向右下走一步。
每次走过一个格子,拿起(并且必须拿上)这个格子上的礼物。
牛妹想知道,她能走到最后拿起的所有礼物体积最小和是多少?
输入
两个正整数N和M,0<N,M<300,每个礼物的体积小于100。
输出
所有礼物的体积最小和。
样例输入
2 3
1 2 3
2 3 4
样例输出
7
提示
(1,1)->(1,2)->(2,3)
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+5;
const int inf=0x3f3f3f3f;
int a[305][305],dp[305][305];
int main()
{
int n,m;
while(~scanf("%d %d",&n,&m)){
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
scanf("%d",&a[i][j]);
}
}
memset(dp,inf,sizeof(dp));
dp[1][1]=a[1][1];
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
if(i+1<=n){//更新下边的体积
dp[i+1][j]=min(dp[i+1][j],dp[i][j]+a[i+1][j]);
}
if(j+1<=m){//更新右边的体积
dp[i][j+1]=min(dp[i][j+1],dp[i][j]+a[i][j+1]);
}
if(i+1<=n&&j+1<=m){//更新右下的体积
dp[i+1][j+1]=min(dp[i+1][j+1],dp[i][j]+a[i+1][j+1]);
}
}
}
printf("%d\n",dp[n][m]);
}
return 0;
}
问题 G: 车站建造问题
题目描述
有108个村庄排在一条公路上,依次编号为0~108-1,相邻村庄距离为1,其中有n个村庄居住着牛牛,居住着牛牛的村庄从小到大依次为a0~an-1,其中保证a0=0。
现在需要建设车站,有两个要求必须被满足:
1、每个有牛牛居住的村庄必须修建车站。
2、相邻车站的距离必须为1或为某个质数。
现给出n和a数组,求需要建设车站的最小数量。
输入
输入数据包含一个数n和一个长度为n的数组a,每一个样例中第一个数字表示n,后面n个数字为数组a中的数据。数组a的下标为0~n-1,保证a数组递增,且a0=0。
1<=n<=1000,a数组中数值保证小于10^8,且ai严格单调递增。
输出
输出一个整数,表示答案,即需要建设车站的最小数量。
样例输入
3
0 7 11
样例输出
4
提示
在0,7,8,11处建造车站,差值分别为7,1,3,符合要求。
每两个相邻车站要质数
如果两个相邻车辆距离不为质数,那就要转换成最少的质数相加
这个其实是哥德巴赫猜想…
如果不知道确实很难受
如果一个非质数x为偶数或者这个数可以分成2+(x-2) (x-2)为质数,那就可以分成两个质素相加
否则最少分成三个质数相加
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=3e5+5;
const int inf=0x3f3f3f3f;
int a[maxn];
bool ju(int a){
if(a==1)return true;
for(int i=2;i*i<=a;++i){
if(a%i==0)return false;
}
return true;
}
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;++i)scanf("%d",&a[i]);
int ans=n;
for(int i=1;i<n;++i){
if(ju(a[i+1]-a[i])==false){
if((a[i+1]-a[i])%2==0||ju(a[i+1]-a[i]-2)){
++ans;
}else{
ans+=2;
}
}
}
printf("%d\n",ans);
return 0;
}
问题 H: DNA序列II
题目描述
牛牛又从生物科研工作者那里获得一个任务,这次牛牛需要帮助科研工作者从DNA序列s中找出最短没有出现在DNA序列s中的DNA片段的长度。
例如:s = AGGTCTA
序列中包含了所有长度为1的(‘A’,‘C’,‘G’,‘T’)片段,但是长度为2的没有全部包含,例如序列中不包含"AA",所以输出2。
输入
输入包括一个字符串s,字符串长度length(1 ≤ length ≤ 20000),其中只包含’A’,‘C’,‘G’,'T’这四种字符。
输出
输出一个正整数,即最短没有出现在DNA序列s中的DNA片段的长度。
样例输入 Copy
AGGTCTA
样例输出 Copy
2
枚举每一个可能的长度进行判断
看看每一个长度的字符串去重(set)后是数量足够。。。。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=3e5+5;
const int inf=0x3f3f3f3f;
string s;
int pow_(int a,int b){//快速幂
int ans=1;
while(b){
if(b&1)ans*=a;
a*=a;
b>>=1;
}
return ans;
}
int main()
{
cin>>s;
int ls=s.length();
for(int len=1;len<=ls;++len){
set<string> se;
for(int i=0;i+len-1<=ls;++i){
string x=s.substr(i,len);//字符串截取函数
se.insert(x);
}
if(se.size()<pow_(4,len)){//长度为len的字符有4^len种组合
printf("%d\n",len);
break;
}
}
return 0;
}