华师一附中OI组
标题:
1^n+2^n+3^n+****m^n的最后k位数
[打印本页]
作者:
admin
时间:
2018-5-1 14:45
标题:
1^n+2^n+3^n+****m^n的最后k位数
这是湖南某年的一个训练题,高精度乘幂和加法,要做很容易,要得高分不容易,我总拿来做基础班的训练题,考察大家代码的控制能力。
作者:
admin
时间:
2018-5-1 14:46
沙发自己抢。此题要想出结果很简单,不用高精度也可以对付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;
}
复制代码
欢迎光临 华师一附中OI组 (http://hsyit.cn/)
Powered by Discuz! X3.2