zoukankan      html  css  js  c++  java
  • 厦门大学线下编程比赛第一题:求和

    给定a和n,计算a+aa+aaa+aaaa+...+a...a(n个a) 的和。
    输入描述:
    测试数据有多组,以文件结尾。每行输入a,n(1<=a,n<=1000000)。
    输出描述:
    由于结果可能比较大,所以请输出答案mod 1000000007。

    仔细审题,假设a=2,n=6;那么要求的和Σ = 2 + 22 + 222 + 2222 + 22222 + 222222

    貌似也不难,只要知道n的长度,只需要把这些数值加起来不就行了吗?

    再看题中提示:由于结果可能比较大,所以请输出答案mod 1000000007。

    如果n很大时,超过定义数据类型的最大长度,这道题使用传统意义上的加法运算,貌似有点不可取。

    看一下这个数据(a=3,n=8)

    3
    33
    333
    3333
    33333
    333333
    3333333
    33333333

    个位数的和是 8 * 3 = 24,十位数的和是7 * 3 + 2= 21 + 2 = 23 (2来自个位和24的进位2),百位数的和是6 * 3 + 2 = 18+2=20 (2来自十位和23的进位2)......通过这个逻辑,我们可以推算出计算 给定a和n,计算a+aa+aaa+aaaa+...+a...a(n个a) 的和 的算法

     1 #include<stdio.h>
     2 #define MAX 1000000
     3 int main()
     4 {
     5     int a = 3,n= 99;
     6     int i,tmp=0;
     7     char array[MAX+1]= {0};
     8     //倒序相加
     9     for(i=0; i<n; i++)
    10     {
    11         tmp = a*(n-i)+tmp;
    12         array[i] = tmp%10;
    13         tmp = tmp/10;
    14     }
    15     while(tmp>0)
    16     {
    17         array[n++] = tmp%10;
    18         tmp = tmp/10;
    19     }
    20     //倒序输出
    21     for(i=n-1; i>=0; i--) printf("%d",array[i]);
    22     printf("
    ");
    23 
    24     return 0;
    25 }

    运行结果:

    可见结果的确很长,题中输出描述:

    由于结果可能比较大,所以请输出答案mod 1000000007

    现在要做的事情就是如何将上面那么长的数据结果mod 1000000007。

    我使用下面这种思路,比如有一个数 123456789,计算 123456789 mod 100007的值

    第一步:123456789 - 100007000 = 23449789

    第二步:23449789 - 10000700 = 13449089

    第三步:13449089 - 10000700 = 3448389

    第四步:3448389 - 1000070 = 2448319

    第五步:2448319 - 1000070 = 1448249

    第六步:1448249 - 1000070 = 448179

    第七步:448179 - 100007 = 348172

    第八步:348172 - 100007 = 248165

    第九步:248165 - 100007 = 148158

    第十步:148158 - 100007 = 48151

    最终求得 123456789 mod 100007 = 48151

    仔细想为什么呢?

    既然思路已经有了,那么就上代码了。

      1 #include<stdio.h>
      2 #define MAX 1000000
      3 int main()
      4 {
      5     int a = 3,n=99;
      6     int i,tmp=0;
      7     char array[MAX+2]= {''};
      8 
      9     /*
     10     在这里我们要论证一点
     11     a的取值范围[1,9]
     12     n的取值范围[1,1000000]
     13     n*a的最大值为9*1000000 << Int32.MaxValue
     14     所以我们可以使用以下逻辑对商数做处理
     15     */
     16     for(i=0; i<n; i++)
     17     {
     18         //倒序相加
     19         tmp = a*(n-i)+tmp;
     20         array[i] = tmp%10;
     21         tmp = tmp/10;
     22     }
     23 
     24     //处理多余商数(这个商数可能比较大,所以要用while循环做进位处理)
     25     while(tmp>0)
     26     {
     27         array[n++] = tmp%10;
     28         tmp = tmp/10;
     29     }
     30 
     31     //倒序输出(打印出结果值)
     32     for(i=n-1; i>=0; i--) printf("%d",array[i]);
     33     printf("
    ");
     34 
     35     int n1=n;
     36     while(n1-10>=0)
     37     {
     38         int b=0;//是不是大于1000000007
     39         if (n-n1==0)
     40         {
     41             //判断前十位是不是大于1000000007,如果不大于,判断前11位
     42             if(!b&&array[n1-1]>1)b=1;
     43             if(!b&&array[n1-2]>0)b=1;
     44             if(!b&&array[n1-3]>0)b=1;
     45             if(!b&&array[n1-4]>0)b=1;
     46             if(!b&&array[n1-5]>0)b=1;
     47             if(!b&&array[n1-6]>0)b=1;
     48             if(!b&&array[n1-7]>0)b=1;
     49             if(!b&&array[n1-8]>0)b=1;
     50             if(!b&&array[n1-9]>0)b=1;
     51             if(!b&&array[n1-10]>7)b=1;
     52             if (!b)
     53             {
     54                 n1--;
     55                 continue;
     56             }
     57         }
     58 
     59 
     60         b=0;//是否需要借位
     61         if (array[n1-10]>=7)
     62         {
     63             array[n1-10]-=7;
     64             b=0;
     65         }
     66         else
     67         {
     68             array[n1-10]+=3;
     69             b=1;
     70         }
     71 
     72         for(i=9; i>=2; i--)
     73         {
     74             if(b)
     75             {
     76                 if(array[n1-i]>=1)
     77                 {
     78                     array[n1-i]-=1;
     79                     b=0;
     80                 }
     81                 else
     82                 {
     83                     array[n1-i]=9;
     84                     b=1;
     85                 }
     86             }
     87         }
     88 
     89         if (n-n1>0)
     90         {
     91             if(b)
     92             {
     93                 array[n1-1]=array[n1]*10+array[n1-1]-2;
     94             }
     95             else
     96             {
     97                 array[n1-1]=array[n1]*10+array[n1-1]-1;
     98             }
     99             array[n1]='';
    100         }
    101         else
    102         {
    103             if(b)
    104             {
    105                 array[n1-1]=array[n1-1]-2;
    106             }
    107             else
    108             {
    109                 array[n1-1]=array[n1-1]-1;
    110             }
    111         }
    112         n1=--n;
    113     }
    114 
    115     //倒序输出
    116     for(i=n-1; i>=0; i--) printf("%d",array[i]);
    117     printf("
    ");
    118 
    119     return 0;
    120 }

    运算结果:

  • 相关阅读:
    动态添加删除控件
    文件下载源码
    poj 1300 欧拉回路、通路 解题报告
    hdu 1232 并查集 或者 深搜
    hdu 2546 01背包问题
    强连通图的判断 hdu 1269
    hdu 2159 二维费用背包问题
    Hdu 3336 kmp+dp解题报告
    hdu 3639 强连通练习使用
    hdu 1712 分组背包问题
  • 原文地址:https://www.cnblogs.com/preacher/p/4739585.html
Copyright © 2011-2022 走看看