7-6 数列求和-加强版 (10 分)
给定某数字A(1≤A≤9)以及非负整数N(0≤N≤100000),求数列之和S=A+AA+AAA+⋯+AA⋯A(N个A)。例如A=1, N=3时,S=1+11+111=123。
输入格式:
输入数字A与非负整数N。
输出格式:
输出其N项数列之和S的值。
输入样例:
1 3
输出样例:
123
附:
时间限制: 200 ms
内存限制: 64 MB
代码长度限制: 16 KB
思路分析
下面说一下思路历程
首先第一种方法:逐个相加,用long long存结果。很明显这种方法不行,数字位数达到了10w+。因此联想到字符串模拟。于是有了第二种方法:大数相加。这种方法加一次的时间复杂度O(n),加n次时间复杂度就是O(n2),并且这道题时间限制改成了200ms(以往的题目一般都是400ms),说明作者另有企图,卡了大数加法的时间。
此处上方法2——大数加法实现的代码
#include <iostream>
using namespace std;
string sum(string s1,string s2)
{
if(s1.length()<s2.length())
{
string temp=s1;
s1=s2;
s2=temp;
}
int i,j;
for(i=s1.length()-1,j=s2.length()-1;i>=0;i--,j--)
{
s1[i]=char(s1[i]+(j>=0?s2[j]-'0':0)); //注意细节
if(s1[i]-'0'>=10)
{
s1[i]=char((s1[i]-'0')%10+'0');
if(i) s1[i-1]++;
else s1='1'+s1;
}
}
return s1;
}
int main()
{
int A, N, tmp = 0;
char c;
string s1, s2;
cin>>A>>N;
if(N == 0) cout<<0<<endl;
else
{
for(int i = 1;i <= N;i++)
{
c = A + '0';
s2 += c;
s1 = sum(s1, s2);
}
cout<<s1<<endl;
}
return 0;
}
判题结果:
果不其然,最后一个数据运行超时。
也就是说,在200ms的情况并且N达到了10w(程序必须要运行10w次)的条件下,我们只能采用一个时间复杂度为O(n)的方法,也是出题人暗示我们的方法。而能满足这个时间复杂度的只有一种情况:递推。先手动模拟找一下规律,然后总结出一条递推公式。也就是当前项可以由前几项通过某种公式得到。
因此,顺着这个思路,列出一些项,找一下规律。
#include <iostream>
using namespace std;
int main()
{
char a[100010];
int flag = 0, A, N;
cin>>A>>N;
if(N == 0) cout<<0;
a[N+1] = '\0';
for(int i = N;i >= 0;i--)
{
a[i] = (i*A + flag)%10 + '0';
flag = (i*A + flag)/10;
}
if(a[0] == '0')
{
for(int i = 1;i <= N;i++) cout<<a[i];
}
else cout<<a<<endl;
return 0;
}