求n^k的前任意位和后任意位

    科技2022-07-14  149

    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 lld\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 lld\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 lld\n",cs,lead,trail); } return 0; }
    Processed: 0.017, SQL: 8