进制转化与递归算法|青训营
这是我参与「第四届青训营 」笔记创作活动的的第6天
这是ICPC第一届算法训练营第一天大致内容
辗转相除法
2进制
#include<stdio.h>
int main()
{
int n,len;
int num[15];
while(scanf("%d",&n)!=EOF)
{
len=0;
while(n!=0)
{
num[len++]=n%2;
n/=2;
}
while(len--)
{
printf("%d",num[len]);
}
printf("\n");
}
return 0;
}
8进制转十进制(小数)
任务描述
本关任务:八进制(以 8 为基数)表示的小数可以用十进制精确地表示。例如,八进制的 0.75 表示为十进制的 0.953125(7/8+5/64)。所有在小数点右边的 n 位八进制数可以用不超过在小数点右边的 3n 位的十进制小数来表示。 编写一个程序,将 0~1 之间(包含 0 和 1)的八进制小数转换为等同的十进制小数。
输入
程序的输入将由若干八进制数组成,每行一个。每个输入八进制数的格式为 0.d1d2d3…dk,其中 di 是八进制数字(0…7),对 k 没有限制。
输出
输出由一系列行组成,格式为 0.d1d2d3…dk[8] = 0.D1D2D3…Dm[10],其中,左式是输入(八进制);右式是等同的十进制值,不能有 0 结尾,即 Dm 不等于 0。
解题思路:
0.75 【8】 = (5/8+7)/8=0.953125 【10】
char d[] d[0]=‘0’,d[1]=‘.’,d[2]=’7’ d[3]=‘5’
过程
(1)5/8的结果要是整数,那么就5000/8=625(5加几个0,8就加几个0)
(2)625+7000=7625
(3)7625000/8 =0.953125
d2= d[3]=5
k保存
5*10=50 50/8=6 余2 ans[0]=6
2*10=20 20/8=2余4 ans[1]=2
4*10=40 40/8=5 余0 ans[2]=5
k=3
d[2]=7
d2=d[2]=7
j变量
7*10+6 =76 76/8=9 余4 ans[0]=9
4*10+2=42 42/8=5 余2 ans[1]=5
2*10+5=25 25/8=3余1 ans[2]=3
1*10 /8=1余2 ans[3]=1
20/8=2余 4 ans[4]=2
40/8=5余0 ans[5]=5
k=6
两个循环:一个循环小数点的后面的位数,另一个循环内部
for(i=len-1;i>1;i--){
d2=d[i]-'0';
int k=0,j=0;
while( j<k||d2)
{
d2=d2*10+ans[j++];
ans[k++]=d2/8;
d2%=8;
}
t=k;
}
#include <iostream>
#include <cstring>
using namespace std;
/*begin*/
int main()
{
int i=0;
char d[100000];
int ans[100000];
int len=0;char c;
while(cin>>d)
{
int t=0;
memset(ans,0,sizeof(ans));
int len=strlen(d);
int d2;
for(int i=len-1;i>1;i--)
{
d2=d[i]-'0';
int k=0,j=0;
while(j<t ||d2 )
{
d2=d2*10+ans[j++];
ans[k++]=d2/8;
d2%=8;
}
t=k;
}cout<<d;
cout<<" [8] = 0." ;
for(int i=0;i<t;i++)
{
cout<<ans[i];
}
cout<<" [10]";
cout<<endl;
}
}
/*end*/
18-1年号字串
任务描述
小明用字母A对应数字1,B对应2,以此类推,用Z对应26。对于27以上的数字,小明用两位或更长位的字符串来对应,例如AA对应27,AB对应28,AZ对应52,LQ对应329。
这题需要边界判断
#include<iostream>
#include<string>
using namespace std;
char str[27]={0,'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
long long ans;
int main()
{
long long n;
while(cin>>n){
string s="";
while(n>0)
{
int m=n%26;
if(m==0)
{
s+='Z';
n=n/26-1;
}
else
{
s+=str[m];
n/=26;
}
}
for(int i=s.size()-1;i>=0;i--)
cout<<s[i];
cout<<endl;
}
}
递归
超级楼梯
题目描述
有一个楼梯共 M 级台阶,刚开始时你在第 1 级,若每次只能跨上 1 级或 2 级,要走上第 M 级, 共有多少种走法?
输入输出格式
输入格式 首先包含一个整数 N,表示测试实例的个数,然后是 N 行数据,每行包含一个整数 M (1≤M≤40),表示楼梯的级数。 输出格式 对于每个测试实例,请输出不同走法的数量。
首先写出样例
f(4)=f(3)+f(2);
f(3)=f(2)+f(1);
#include<iostream>
using namespace std;
int main()
{
int n;
int num[100];
num[0]=0;
num[1]=0;
num[2]=1;
num[3]=2;
for(int i=4;i<=40;i++)
num[i]=num[i-1]+num[i-2];
cin>>n;
int x;
while(n--)
{
scanf("%d",&x);
cout<<num[x]<<endl;
}
}
数列求值
任务描述
本关任务:给定数列1,1,1,3,5,9,17,…,从第4项开始,每项都是前三项的和。求第n项的最后四位数字。
坑:越界和数值范围
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int mod = 1e4;
LL dp[20190325]; //数列从1下标开始
int main() {
dp[1]=1;
dp[2]=1;
dp[3]=1;
for(int i=4;i<=20190324;i++)
dp[i]=(dp[i-1]+dp[i-2]+dp[i-3])%mod;
int n;
while(cin>>n){
cout<<dp[n]<<endl;
}
}