厦门大学线下编程比赛第一题:求和

给定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("\n");
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]= {'\0'};
  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("\n");
 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]='\0';
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("\n");
118 
119     return 0;
120 }

 

 

运算结果:

 

posted @ 2015-08-18 15:41  牧师/preacher  阅读(1198)  评论(1编辑  收藏  举报