You are given two integers: n and k, your task is to find the most significant three digits, and least significant three digits of nk.
**Input
Input starts with an integer T (≤ 1000), denoting the number of test cases.
Each case starts with a line containing two integers: n (2 ≤ n < 231) and k (1 ≤ k ≤ 107).
Output
For each case, print the case number and the three leading digits (most significant) and three trailing digits (least significant). You can assume that the input is given such that nk contains at least six digits.
Sample Input
5
123456 1
123456 2
2 31
2 32
29 8751919
Sample Output
Case 1: 123 456
Case 2: 152 936
Case 3: 214 648
Case 4: 429 296
Case 5: 665 669**
题意:求n^k的前三位和最后三位
求后三位的思路:快速幂+求模,如果不懂快速幂板子的请看大佬的详解
如果b实在是超级大,也可以先用欧拉降幂使b减小,然后在使用快速幂+求模,当然该题不降低b也可以过,如果想了解,就看一下代码3
ll quickpowtrail(ll x,ll y,ll z)
{//表示求x^y%z
ll ans=1;
while(y)
{
if(y&1)
ans=ans*x%z;
x=x*x%z;
y/=2;
}
return ans%n;
}
求前三位有两种思路:
思路1:与快速幂+求模的类似,只是稍微做下改动
double quickpowlead(ll a,ll y,ll z)
{//这里强调x,ans为浮点数
double x=(double)a;
double ans=1.0;
while(y)
{
if(y&1)
{
ans=ans*x;
while(ans>=z)
ans/=10;//重点:ans必须是浮点数,每次除以10要保留小数部分
}
x=x*x;
y/=2;
while(x>=z)
x/=10;//重点:x必须是浮点数,每次除以10要保留小数部分
}
return ans;
}
思路2:数学方法,很简单,也很短,也很容易理解
有一点需要知道:10^z可以任意表示一个整数,前提z可以是浮点数
接下来n^k=10^z
log10(n^k)=log10(10^z);
z=k*log10(n);
拆z=x+y;(x取整数,y取小数)
10^z=10^(x+y)=10^x*10^y
明显10^x指数控制位数,10^y控制的是每位上的数字
第一步求:z=k*log10(n)
第二步:x=(int)z;
第三步:y=z-x;
第四步:trail=(int)(10^y*100)
结束
double z=1.0*k*log10(n*1.0);
ll x=(ll)z;
double y=z-x;
ll lead=(ll)(pow(10,y)*100)
全部代码
代码1:
#include<stdio.h>
#include<math.h>
typedef long long ll;
double quickpowlead(ll a,ll y,ll z)
{
double x=(double)a;
double ans=1.0;
while(y)
{
if(y&1)
{
ans=ans*x;
while(ans>=z)
ans/=10;//重点:ans必须是浮点数,每次除以10要保留小数部分
}
x=x*x;
y/=2;
while(x>=z)
x/=10;//重点:x必须是浮点数,每次除以10要保留小数部分
}
return ans;
}
ll quickpowtrail(ll x,ll y,ll z)
{
ll ans=1;
while(y)
{
if(y&1)
ans=ans*x%z;
x=x*x%z;
y/=2;
}
return ans;
}
int main()
{
ll t,cs;
scanf("%lld",&t);
for(cs=1;cs<=t;cs++)
{
ll n,k;
scanf("%lld %lld",&n,&k);
ll lead=quickpowlead(n,k,1000);
ll trail=(ll)quickpowtrail(n,k,1000);
printf("Case %d: %lld %03lld\n",cs,lead,trail);
}
return 0;
}
代码2:
#include<stdio.h>
#include<math.h>
typedef long long ll;
ll quickpow(ll x,ll y,ll z)
{
ll ans=1;
while(y)
{
if(y&1)
ans=ans*x%z;
x=x*x%z;
y/=2;
}
return ans;
}
int main()
{
int t,cs;
scanf("%d",&t);
for(cs=1;cs<=t;cs++)
{
int n,k;
scanf("%d %d",&n,&k);
double z=1.0*k*log10(n*1.0);
ll x=(ll)z;
double y=z-x;
ll lead=(ll)(pow(10,y)*100);//10^y
ll trail=quickpow(n,k,1000);
printf("Case %d: %lld %03lld\n",cs,lead,trail);
}
return 0;
}
代码3:
#include<stdio.h>
#include<math.h>
typedef long long ll;
ll phi(ll n)
{//求1,n-1内与n互质的个数
ll i,rea=n;
for(i=2;i*i<=n;i++)
{
if(n%i==0)
{
rea=rea-rea/i;
while(n%i==0)
n/=i;
}
}
if(n>1)
rea=rea-rea/n;
return rea;
}
ll quickpow(ll x,ll y,ll z)
{
ll ans=1;
while(y)
{
if(y&1)
ans=ans*x%z;
x=x*x%z;
y/=2;
}
return ans;
}
int main()
{
int t,cs;
scanf("%d",&t);
for(cs=1;cs<=t;cs++)
{
int n,k;
scanf("%d %d",&n,&k);
double z=1.0*k*log10(n*1.0);
ll x=(ll)z;
double y=z-x;
ll lead=(ll)(pow(10,y)*100);//10^y
ll rea=phi(1000);
ll trail=quickpow(n,k%rea+rea,1000);
注意k%rea+rea
公式:a^b%c==a^(b%rea+rea)%c,
如若了解为什么,就网上搜搜欧拉函数的解释吧
printf("Case %d: %lld %03lld\n",cs,lead,trail);
}
return 0;
}