zoukankan      html  css  js  c++  java
  • 洛谷P1255数楼梯(大数,高精度加法)

    题目链接:https://www.luogu.org/problemnew/show/P1255

    这题挺有意思

    首先麻烦的一点,要推出方案数:f[n]=f[n-1]+f[n-2]。

    然后还不算完,大数运算开始

    long long,unsigned long long,60分

    普通高精大数加法过了,但1400ms

     1 #include <iostream>
     2 #include <string>
     3 #include <algorithm>
     4 #include <cstdio>
     5 #include <cstring>
     6 #include <cmath>
     7 using namespace std;
     8 typedef long long ll;
     9 typedef unsigned long long ull;
    10 const int maxn=1e6+5;
    11 char a[maxn],b[maxn],d[maxn];
    12 int c[maxn];
    13 
    14 int zfs(char c)
    15 {
    16     if(c==0) return 0;
    17     else if(c>='0' && c<='9') return c-48;
    18     else return c-65+10;
    19 }
    20 
    21 void Add(int len1,int len2)
    22 {
    23     //交换工作,倒序
    24     int p=-1;
    25     for(int i=len1-1;i>=0;i--) d[++p]=a[i];
    26     for(int i=0;i<=len1-1;i++) a[i]=d[i];
    27     p=-1;
    28     for(int i=len2-1;i>=0;i--) d[++p]=b[i];
    29     for(int i=0;i<=len2-1;i++) b[i]=d[i];
    30 
    31     //模拟计算
    32     int len=max(len1,len2);
    33     for(int i=0;i<=len-1;i++)
    34     {
    35         int x=zfs(a[i]),y=zfs(b[i]);
    36         c[i]+=x+y;
    37         while(c[i]>=10)
    38         {
    39             c[i]-=10;
    40             c[i+1]+=1;
    41         }
    42     }
    43 
    44     //更新操作,重新赋值
    45     p=-1;
    46     for(int i=len2-1;i>=0;i--) a[++p]=b[i];
    47     p=-1;
    48     if(c[len]!=0) b[++p]=c[len]+48;
    49     for(int i=len-1;i>=0;i--) b[++p]=c[i]+48;
    50     memset(c,0,sizeof(c));
    51 
    52     //输出
    53     if(c[len]!=0) cout<<c[len];
    54     for(int i=len-1;i>=0;i--) cout<<c[i];
    55     cout<<endl;
    56 
    57 }
    58 
    59 int main()
    60 {
    61     ios::sync_with_stdio(false); cin.tie(0);
    62 
    63     cin>>n;
    64     a[0]='1';
    65     b[0]='2';
    66     if(n==0) { cout<<'0'<<endl; return 0; }
    67     if(n==1) { cout<<'1'<<endl; return 0; }
    68     if(n==2) { cout<<'2'<<endl; return 0; }
    69     for(int i=3;i<=n;i++)
    70     {
    71         int len1=strlen(a),len2=strlen(b);
    72         Add(len1,len2);
    73     }
    74 
    75     cout<<b<<endl;
    76 
    77     return 0;
    78 }

    大数加法的一个技巧:

    不直接输入运算数时,最好用int数组(这时候可以一个一个存),省去了字符转换的时间

    要直接输入运算数时,只能用char数组输入(int多位会错没法计算)

    int数组,1300ms(就是交换值更新下一轮的时间太大)

     1 #include <iostream>
     2 #include <string>
     3 #include <algorithm>
     4 #include <cstdio>
     5 #include <cstring>
     6 #include <cmath>
     7 using namespace std;
     8 typedef long long ll;
     9 typedef unsigned long long ull;
    10 const int maxn=1e6+5;
    11 int a[maxn],b[maxn];
    12 int c[maxn];
    13 int len=1;
    14 int n;
    15 
    16 void Add()
    17 {
    18     //计算
    19     for(int i=0;i<=len-1;i++)
    20     {
    21         c[i]+=a[i]+b[i];
    22         while(c[i]>=10)
    23         {
    24             c[i]-=10;
    25             c[i+1]+=1;
    26         }
    27     }
    28     if(c[len]) len++;
    29 
    30     //更新为了下次轮回(应该就是这里交换很费时间没错了!想办法不要交换用别的方法代替!)
    31     for(int i=0;i<=len-1;i++) a[i]=b[i];
    32     for(int i=0;i<=len-1;i++) b[i]=c[i];
    33     memset(c,0,sizeof(c));
    34 }
    35 
    36 int main()
    37 {
    38     ios::sync_with_stdio(false); cin.tie(0);
    39 
    40     cin>>n;
    41     if(n==0) { cout<<'0'<<endl; return 0; }
    42     if(n==1) { cout<<'1'<<endl; return 0; }
    43     if(n==2) { cout<<'2'<<endl; return 0; }
    44     a[0]=1;
    45     b[0]=2;
    46     for(int i=3;i<=n;i++)
    47     {
    48         Add();
    49     }
    50 
    51     if(b[len]) cout<<b[len];
    52     for(int i=len-1;i>=0;i--) cout<<b[i];
    53     cout<<endl;
    54 
    55     return 0;
    56 }

    另一种很不错的大数加法写法107ms(其实就是用二维数组优化了上面的,不用再每轮交换更新赋值了!)

    思路大概是用数组f[k][j]来存储走k个阶梯所用的步数 最后循环输出

     1 #include <iostream>
     2 #include <string>
     3 #include <algorithm>
     4 #include <cstdio>
     5 #include <cstring>
     6 #include <cmath>
     7 using namespace std;
     8 typedef long long ll;
     9 typedef unsigned long long ull;
    10 const int maxn=1e6+5;
    11 int c[maxn];
    12 int f[5005][5005];
    13 int len=1;
    14 int n;
    15 
    16 
    17 void Add(int k)
    18 {
    19     //计算
    20     for(int i=1;i<=len;i++)
    21     {
    22         f[k][i]+=f[k-1][i]+f[k-2][i];
    23         while(f[k][i]>=10)
    24         {
    25             f[k][i]-=10;
    26             f[k][i+1]+=1;
    27         }
    28     }
    29 
    30     if(f[k][len+1]) len++;
    31 
    32 }
    33 
    34 int main()
    35 {
    36     ios::sync_with_stdio(false); cin.tie(0);
    37 
    38     cin>>n;
    39     if(n==0) { cout<<'0'<<endl; return 0; }
    40     if(n==1) { cout<<'1'<<endl; return 0; }
    41     if(n==2) { cout<<'2'<<endl; return 0; }
    42     f[1][1]=1; f[2][1]=2;
    43     for(int i=3;i<=n;i++)
    44     {
    45         Add(i);
    46     }
    47 
    48     for(int i=len;i>=1;i--) cout<<f[n][i];
    49     cout<<endl;
    50 
    51     return 0;
    52 }

    完。

  • 相关阅读:
    python的复制,深拷贝和浅拷贝的区别(转)
    linux下ffmpeg安装(转)
    Linux下的tar压缩解压缩命令详解(转)
    centos7安装python-pip(转)
    爬山算法和模拟退火算法简介
    协方差、协方差矩阵定义与计算
    七种常见阈值分割代码(Otsu、最大熵、迭代法、自适应阀值、手动、迭代法、基本全局阈值法)
    Canny边缘检测算法原理及其VC实现详解(二)
    Canny边缘检测算法原理及其VC实现详解(一)
    perforce变量配置与使用
  • 原文地址:https://www.cnblogs.com/redblackk/p/9797230.html
Copyright © 2011-2022 走看看