洛谷P1050循环题解--zhengjun

题目描述

乐乐是一个聪明而又勤奋好学的孩子。他总喜欢探求事物的规律。一天,他突然对数的正整数次幂产生了兴趣。

众所周知,\(2\)的正整数次幂最后一位数总是不断的在重复\(2,4,8,6,2,4,8,6…\)我们说\(2\)的正整数次幂最后一位的循环长度是\(4\)(实际上\(4\)的倍数都可以说是循环长度,但我们只考虑最小的循环长度)。类似的,其余的数字的正整数次幂最后一位数也有类似的循环现象:

    循环    循环长度
2   2,4,8,6   4
3   3,9,7,1   4
4   4,6       2
5   5         1
6   6         1
7   7,9,3,1   4
8   8,4,2,6   4
9   9,1       2

这时乐乐的问题就出来了:是不是只有最后一位才有这样的循环呢?对于一个整数\(n\)的正整数次幂来说,它的后\(k\)位是否会发生循环?如果循环的话,循环长度是多少呢?

注意:

  1. 如果\(n\)的某个正整数次幂的位数不足\(k\),那么不足的高位看做是\(0\)
  2. 如果循环长度是\(L\),那么说明对于任意的正整数\(a,n\)\(a\)次幂和\(a+L\)次幂的最后\(k\)位都相同。

输入格式

一行,包含\(2\)个整数\(n(1 \le n < 10^{100})\))和\(k(1 \le k \le 100)\)\(n\)\(k\)之间用一个空格隔开,表示要求\(n\)的正整数次幂的最后\(k\)位的循环长度。

输出格式

一个整数,表示循环长度。如果循环不存在,输出\(-1\)

输入输出样例

输入 #1 复制
32 2
输出 #1 复制
4

说明/提示

对于\(30\%\)的数据,\(k \le 4\)

对于全部的数据,\(k \le 100\)

\(NOIP2005\)普及组第四题

思路

首先,这道题一定是要高精度的,答案同样。

第一个方法肯定是暴力,知道循环,可是答案都要高精度了能不\(TLE\)

那么,正解就是这样的。

比如说\(78910912\) \(4\) (第三个数据点)

取后面的四位就是\(912\)

首先,我们可以求出最后一位的循环长度,很显然是\(4\)

2,4,8,6,2
        ^

接着,怎么求出后两位的循环长度呢,因为后两位要循环的话必须先让最后一位循环,再看第二位是否循环,那么直接每一次乘上个\(4\)\((\)就是\(12^4\bmod100=36)\),因为\(4\)次个位才会循环,判断是否循环。

12,32,52,72,92,12
               ^

所以,后面两位要循环就要\(20\)次,因为个位是一个小循环\(4\)次,十位是在个位的基础上大循环\(5\)次。

接下来求后面三位循环,\(912^{20}\bmod 1000=176\)

912,512,112,712,312,912
                    ^

五位一循环,所以,后三位的循环长度就是\(20\times5=100\)

最后就是四位了

\(912^{100}\bmod 10000=3376\)

912,8912,6912,4912,2912,912
                        ^

所以最终的答案就是\(500\)

代码

#include<bits/stdc++.h>
#define cpy(x,y) for(int v=1;v<=k;v++)x[v]=y[v];
using namespace std;
int xh[11]={1,1,4,4,2,1,1,4,4,2};
int k,b[205],c[205],d[205],p[205],q[205],ans[205],tot1,tot2=2,t;
char a[105];
void mul1(int x[],int y[],int z[]){
    for(int i=1;i<=k;i++){
        for(int j=1;j<=k;j++){
            z[i+j-1]+=x[i]*y[j];
            z[i+j]+=z[i+j-1]/10;
            z[i+j-1]%=10;
        }
	}
}
void mul2(int x[],int y,int z[]){
    for(int i=1;i<=k;i++){
        z[i]+=x[i]*y;
        z[i+1]+=z[i]/10;
        z[i]%=10;
    }
}
int main(){
    scanf("%s%d",a+1,&k);
	int len=strlen(a+1);
    for(int i=len;i>=len-k+1;i--)
	    c[++tot1]=a[i]-'0';
    for(int i=1;i<=k;i++)
	    b[i]=c[i];
    for(int i=1;i<xh[c[1]];i++){
        memset(d,0,sizeof(d));//这个一定要加,如果放在mul1里面就会wa
        mul1(b,c,d);
        cpy(b,d);
    }
    ans[1]=xh[c[1]];
    cpy(q,b);
    cpy(p,b);
    while(tot2<=k){
        cpy(b,c);
        while(t<11){
            memset(d,0,sizeof(d));
            mul1(b,p,d);
            t++;
            cpy(b,d);
            if(b[tot2]==c[tot2])
			    break;
            memset(d,0,sizeof(d));
            mul1(q,p,d);
            cpy(q,d);
        }
        if(t==11){//无解
		    printf("-1");
			return 0;
		}
        cpy(p,q);
        memset(d,0,sizeof(d));
        mul2(ans,t,d);
        for(int i=1;i<=100;i++)//计算答案
		    ans[i]=d[i];
        tot2++;
        t=0;
    }
    int anslen=101;
    while(ans[anslen]==0&&anslen>1)
	    anslen--;
    for(int i=anslen;i>=1;i--)
	    printf("%d",ans[i]);
	return 0;
}

我最后只想说一句,那些用\(python,java\)做的不知道比赛不支持吗?

谢谢--zhengjun

posted @ 2022-06-10 19:16  A_zjzj  阅读(95)  评论(0编辑  收藏  举报