|
沙发
楼主 |
发表于 2018-5-1 14:46:01
|
只看该作者
沙发自己抢。此题要想出结果很简单,不用高精度也可以对付10-20位以下的数值,可以写一个用来对拍。但是mnk大约到几百的时候就不行了,优化的技巧很考验人的编程能力和分析能力。当n比较小的时候,快速幂没有太大的必要。甚至单精度乘速度更快。
当k比较小的时候,压位优势就不明显。
当m比较小的时候,就直接计算m^n不需要保存先前的计算结果。
总之,此题很值得一做。
我没有压位,参考程序
- //1^n+2^n+****m^n最后k位
- #include<iostream>
- #include<iomanip>
- using namespace std;
- int a[1000][1000],s[1000],t[1000];
- //a是单个m^n的值,s是总和,t是临时计算的值
- int maxp;
- int m,n,k;
- int i,j;
- void mul(int a[],int b[]) //a=a*b的高精度形式
- {
- int i,j,x;
- int c[1000];
- for (i=0; i<=999; i++) c[i]=0;
- for(i=0; i<=k-1; i++)
- for(j=0; j<=k-i-1; j++) c[i+j]+=a[i]*b[j];
- for(i=0; i<=k-2; i++)
- {
- x=c[i];
- c[i]=x%10;
- c[i+1]+=x/10;
- }
- for(i=0; i<=k-1; i++)a[i]=c[i];
- }
- void pow(int a[],int m,int n) //a=m^n的高精度形式
- {
- int i,j,x;
- int ss[1000];
- for (i=0; i<=999; i++) ss[i]=a[i]=0;
- ss[0]=m;a[0]=1;
- while (n>0)
- {
- if (n%2==1) mul(a,ss);
- n=n/2;mul(ss,ss);
- }
- }
- int main()
- {
- cin>>m>>n>>k;
- for (i=2; i<=m; i++)
- {
- j=2;while (i%j!=0) j++;
- if (j==i)
- {
- pow(s,j,n);
- }
- else
- {
- for (int jj=0; jj<=k-1; jj++)
- {
- s[jj]=a[j][jj];
- t[jj]=a[i/j][jj];
- }
- mul(s,t);
- }
- for (int jj=0; jj<=k-1; jj++) a[i][jj]=s[jj];
- //for (j=k-1; j>=0; j--) cout<<a[i][j];cout<<endl; 输出每个单项的值
- }
- //把 a 加到s
- s[0]=1;for (i=1;i<=k-1;i++) s[i]=0;
- for (j=1; j<=m; j++)
- for (i=0;i<=k-1;i++) s[i]=s[i]+a[j][i];
- //处理s的进位
- for (i=0;i<=k-2;i++) {int x=s[i];s[i]=x%10;s[i+1]=s[i+1]+x/10;}
- //输出
- for (j=k-1; j>=0; j--) cout<<s[j];
- /*对拍验算
- cout<<"======\n";
- long long pp=0,ss=0,tt=0;
- for (m=1;m<=10;m++)
- {ss=1;for (n=1;n<=10;n++) ss=ss*m;tt=tt+ss;}
- cout<<tt;
- */
- return 0;
- }
复制代码
|
|