Nyoj 114 某种序列(大数)

某种序列

时间限制:3000 ms  |  内存限制:65535 KB

难度:4

描述

数列A满足An = An-1 + An-2 + An-3, n >= 3 
编写程序,给定A0, A1 和 A2, 计算A99

输入

输入包含多行数据 
每行数据包含3个整数A0, A1, A2 (0 <= A0, A1, A2 <= 100000000) 
数据以EOF结束

输出

对于输入的每一行输出A99的值

样例输入

1 1 1

样例输出

69087442470169316923566147

  1. #include <stdio.h>
  2. #include <string.h>
  3. #define MAX 110
  4. #define MAXN 100
  5. #define CLR(arr) memset(arr,0,sizeof(arr))
  6. char a[4][MAX],c[3][MAX],temp1[MAX],temp2[MAX];
  7. char r[4][MAX];
  8. char b[3][MAX];
  9. void Strrev(int n,char *a){
  10.     int j,len=n/2;
  11.     char t;
  12.     for(j=0;j<=len;j++){
  13.         t=a[j];
  14.         a[j]=a[n-j];
  15.         a[n-j]=t;
  16.     }
  17. }
  18. void add(const
    char *a,const
    char *b,char *r)//将a+b的结果保存在r中
  19. {
  20.     int i=strlen(a)-1,j=strlen(b)-1,c=0,k=0;
  21.     if(a[0]==‘0‘){
  22.         memcpy(r,b,sizeof(temp1));
  23.         return ;
  24.     }
  25.     if(b[0]==‘0‘){
  26.         memcpy(r,a,sizeof(temp1));
  27.         return ;
  28.     }
  29.     while(i>=0&&j>=0){
  30.         r[k]=a[i--]+b[j--]+c-‘0‘;
  31.         if(r[k]>‘9‘){
  32.             r[k]-=10;
  33.             c=1;
  34.         }
  35.         else c=0;
  36.         k++;
  37.     }
  38.     while(i>=0){
  39.         r[k]=a[i--]+c;
  40.         if(r[k]>‘9‘){
  41.             r[k]-=10;
  42.             c=1;
  43.         }
  44.         else c=0;
  45.         k++;
  46.     }
  47.     while(j>=0){
  48.         r[k]=b[j--]+c;
  49.         if(r[k]>‘9‘){
  50.             r[k]-=10;
  51.             c=1;
  52.         }
  53.         else c=0;
  54.         k++;
  55.     }
  56.     if(c)r[k]=‘1‘;
  57.     else k--;
  58.     Strrev(k,r);
  59. }
  60. void mulp(const
    char *a,const
    char *b,char *r)//将a*c的结果保存在r中
  61. {
  62.     int lena=strlen(a),lenb=strlen(b),i,j,k,c;
  63.     for(i=lenb-1;i>=0;i--){
  64.         j=lena-1;
  65.         c=0;
  66.         for(k=0;j>=0;k++){
  67.             temp1[k]=(a[j--]-‘0‘)*(b[i]-‘0‘)+c;
  68.             if(temp1[k]>9){
  69.                 c=(temp1[k])/10;
  70.                 temp1[k]%=10;
  71.             }
  72.             else c=0;
  73.             temp1[k]+=‘0‘;
  74.         }
  75.         if(c)temp1[k]=c+‘0‘;
  76.         else k--;
  77.         Strrev(k,temp1);
  78.         for(j=1;j<lenb-i;j++)temp1[k+j]=‘0‘;
  79.         memcpy(temp2,r,sizeof(temp2));
  80.         memset(r,0,sizeof(temp1));
  81.         add(temp1,temp2,r);
  82.         CLR(temp1);
  83.     }
  84.     if(r[0]==‘0‘||r[0]==0){
  85.         CLR(r);
  86.         r[0]=‘0‘;
  87.     }
  88. }
  89. int main(){
  90.     int i,j;
  91.     b[0][0]=‘1‘;
  92.     b[1][0]=‘0‘;
  93.     b[2][0]=‘0‘;
  94.     for(j=3;j<MAXN;j++){
  95.         CLR(temp1);
  96.         add(b[(j-1)%4],b[(j-2)%4],temp1);
  97.         CLR(b[j%4]);
  98.         add(temp1,b[(j-3)%4],b[j%4]);
  99.     }//打出An中a0系数的表,这里使用取模循环来减小空间
  100.     memcpy(c[0],b[(MAXN-1)%4],sizeof(c[0]));
  101.     CLR(b);
  102.     b[0][0]=‘0‘;
  103.     b[1][0]=‘1‘;
  104.     b[2][0]=‘0‘;
  105.     for(j=3;j<MAXN;j++){
  106.         CLR(temp1);
  107.         add(b[(j-1)%4],b[(j-2)%4],temp1);
  108.         CLR(b[j%4]);
  109.         add(temp1,b[(j-3)%4],b[j%4]);
  110.     }//a1系数的表
  111.     memcpy(c[1],b[(MAXN-1)%4],sizeof(c[0]));
  112.     CLR(b);
  113.     b[0][0]=‘0‘;
  114.     b[1][0]=‘0‘;
  115.     b[2][0]=‘1‘;
  116.     for(j=3;j<MAXN;j++){
  117.         CLR(temp1);
  118.         add(b[(j-1)%4],b[(j-2)%4],temp1);
  119.         CLR(b[j%4]);
  120.         add(temp1,b[(j-3)%4],b[j%4]);
  121.     }//a2系数
  122.     memcpy(c[2],b[(MAXN-1)%4],sizeof(c[0]));
  123.     while(scanf("%s%s%s",a[0],a[1],a[2])!=EOF){//读取a0 a1 a2
  124.         for(i=0;i<3;i++){
  125.             CLR(temp1);
  126.             mulp(c[i],a[i],r[i]);//计算a1,a2,a3各自和
  127.         }
  128.         CLR(temp1);
  129.         add(r[0],r[1],temp1);
  130.         add(temp1,r[2],r[3]);
  131.         printf("%s\n",r[3]);//累加到r3中并输出
  132.         CLR(a);
  133.         CLR(r);//清0
  134.     }
  135.    return 0;
  136. }

这题的难点在于大数,加法我已经很熟了,但是乘法还没弄过,乘法是建立在加法的基础上,还是小学生算术做原理,逐位进行乘法并累加,主要有以下几点特别,进位不再只是1而是两个数向乘后取十位数,保留数不是减10而是取模10,而且+‘0‘转换成字符要放最后,否则为计算错误。我的方法就是把每一位都当个位,与另一个数相乘,得到的数再进行补位(也就是在结尾加0),虽说大数是主要难点,但是这题其实只要用加法,直接累加也能AC,就是对每个a0,a1,a2,我们直接加法递推出结果,还可以用循环队列的方法减小空间复杂度(其实也没必要,100*100左右还是不用担心MLE的),但是我们也可以发现,任意An可以表示成 a0,a1,a2的非负倍数和,而且对于An系数与 a0,a1,a2无关,于是我们可先递推出A99对应的各自系数,在用乘法与加法计算得出结果,我一开始就想到要这样,但是实现起来用了好久,早上1点起床,2点开始做,下午5点多才AC了,3个多小时,如果是比赛不知道死的多惨,注意时间耗在了加法乘法的实现与测试上,还有一开始以为系数不会很大,直接用int,发现溢出改用unsign int ,发现是正数(废话)愚蠢地以为安全了,就写了个数字转字符串函数,然后动手写高精度了,后来弄完高精度发现连测试样例都不对(这里要感谢一下样例,如果他犯贱用个0,0,0我就要搞更久),就猜想是不是爆了unsign int,换了下longlong,还是错,遍明白了自古斐波必大数的道理,只能改掉重来,然后交了,一次AC而且还是时间0 这题还是挺水了,居然还能难度4(你就会调软难度4 捏(╬▔皿▔)凸)几乎没什么坑,0,0,0算一个,但是这坑太容易想到了,于是能一次过,但耗时太长了,不过下次遇到大数类我应该能很快撸过,因为有了经验了,大数太常用了,需要更加地熟练,接下来想看一下图论的东西,又要啃那本白书了。。嗯,今天可以早点睡了o(* ̄▽ ̄*)ブ,对了,将memset弄成CLR参数宏这招真方便(●‘?‘●)

时间: 2024-11-05 00:32:42

Nyoj 114 某种序列(大数)的相关文章

nyoj 114 某种序列 【java大数】

rt 代码: import java.util.Scanner; import java.math.*; public class Main{ public static void main(String[] args){ Scanner cin = new Scanner(System.in); BigInteger a, b, c, ans, temp1, temp2; while(cin.hasNextBigInteger()){ a = cin.nextBigInteger(); b =

nyoj 114某种排序(水 大数+优化大数)

某种序列 时间限制:3000 ms  |  内存限制:65535 KB 难度:4 描述 数列A满足An = An-1 + An-2 + An-3, n >= 3 编写程序,给定A0, A1 和 A2, 计算A99 输入 输入包含多行数据 每行数据包含3个整数A0, A1, A2 (0 <= A0, A1, A2 <= 100000000) 数据以EOF结束 输出 对于输入的每一行输出A99的值 样例输入 1 1 1 样例输出 69087442470169316923566147 来源 水

nyoj114 某种序列(大数)

题目114 题目信息 运行结果 本题排行 讨论区 某种序列 时间限制:3000 ms  |  内存限制:65535 KB 难度:4 描述 数列A满足An = An-1 + An-2 + An-3, n >= 3 编写程序,给定A0, A1 和 A2, 计算A99 输入 输入包含多行数据 每行数据包含3个整数A0, A1, A2 (0 <= A0, A1, A2 <= 100000000) 数据以EOF结束 输出 对于输入的每一行输出A99的值 样例输入 1 1 1 样例输出 690874

NYOJ题目114某种序列

----------------------------------------- 迭代相加即可 AC代码: 1 import java.math.BigInteger; 2 import java.util.Scanner; 3 4 public class Main { 5 6 public static void main(String[] args) { 7 8 Scanner sc=new Scanner(System.in); 9 10 while(sc.hasNextBigInte

NYOJ 某种序列

某种序列 时间限制:3000 ms  |  内存限制:65535 KB 难度:4 描述 数列A满足An = An-1 + An-2 + An-3, n >= 3 编写程序,给定A0, A1 和 A2, 计算A99 输入 输入包含多行数据 每行数据包含3个整数A0, A1, A2 (0 <= A0, A1, A2 <= 100000000) 数据以EOF结束 输出 对于输入的每一行输出A99的值 样例输入 1 1 1 样例输出 69087442470169316923566147 #inc

POJ 3982 序列 大数题解

又是一道大数相加的题目,直接模板或者Java都可以水过了. 循环相加33次就可以了,计算出A99是第几个,准确输出答案. #include <stdio.h> #include <string> #include <algorithm> using std::string; const int MAX_B = 5120; char buf[MAX_B]; int id = 0, len = 0; inline char getFromBuf() { if (id >

NYOJ 370 波动序列

收到自己买的STM32F103ZE为主芯片的开发板,标志着我正式进入实践阶段,之前看了不少ARM的资料,都是零零散散的,也没有什么系统的总结,总觉得找到真正的感觉,就下决心买开发板,至于为什么选择STM32,很简单,适合自己.好了,废话少说,以下是我今天收到开发板后的学习总结. 由于还不清楚什么如何运作,就按照提供的资料的视频一步一步做: 第1步:上电检测开发板是否正常. 第2步:安装驱动和软件. 驱动:JLINK驱动---用于仿真调试用. CH340驱动(USB串口驱动)-----用于开发板与

BZOJ 1005: [HNOI2008]明明的烦恼 Purfer序列 大数

1005: [HNOI2008]明明的烦恼 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php?id=1005 Description 自从明明学了树的结构,就对奇怪的树产生了兴趣...... 给出标号为1到N的点,以及某些点最终的度数,允许在任意两点间连线,可产生多少棵度数满足要求的树? Input 第一行为N(0 < N < = 1000),接下来N行,第i+1行

nyoj 28-大数阶乘 (大数模板)

28-大数阶乘 内存限制:64MB 时间限制:3000ms Special Judge: No accepted:19 submit:39 题目描述: 我们都知道如何计算一个数的阶乘,可是,如果这个数很大呢,我们该如何去计算它并输出它? 输入描述: 输入一个整数m(0<m<=5000) 输出描述: 输出m的阶乘,并在输出结束之后输入一个换行符 样例输入: 复制 50 样例输出: 3041409320171337804361260816606476884437764156896051200000