进制转化与递归算法|青训营笔记

120 阅读3分钟

进制转化与递归算法|青训营

这是我参与「第四届青训营 」笔记创作活动的的第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;
​
 }
​
​
}