zoukankan      html  css  js  c++  java
  • ABC222 G

    ABC222 G - 222

    解题思路

    首先看到题目我们发现,对于 (99983)(2) 等数字答案都等于这个数本身 (-1)。我们又发现这些数是质数,非常自然想到费马小定理。但是赛时我只想到了这一点,并没有把费马小定理推广到欧拉函数上。而这是解题的关键。

    我们知道,对于任意的 (x),对于(gcd(a,x)=1)有:

    [a^{varphi (x)}equiv 1mod x ]

    这就是欧拉定理。问题是我们如何与这道题联系起来呢?我们其实很容易对于一个数 (x=2cdot k (kin Z)) 若有 (xmid 222dots222),一定有 (kmid 111dots 111)。这有什么用呢?我们可以在想一步,若对于 (x=2cdot k+1 (kin Z)) 我们有 (xmid 111dots 111)

    然后怎么办?我们尝试找一下 (111dots 111) 的性质,发现它其实可以表示为 (frac{10^n-1}9) 的形式。这好像和欧拉定理可以联系上了。同上面的变化方式,我们可以将 (x) 或者 (k) 乘上 (9),使得得到的新数 (x') 满足 (x'mid 10^n-1)

    是不是柳暗花明又一村了?我们可以进一步推柿子。

    [10^nequiv 1mod x' ]

    那我们就要找最小的满足条件的 (n)。由欧拉定理,(varphi(x')) 一定满足条件(只要 (gcd(x',10)=1))。那么我们输出 (varphi(x')) 就可以了吗?

    达咩达咩。

    我们发现对于 (x=37)(n=3) 就满足条件。也就是说,(varphi(x')) 不一定是最小的满足条件的数。满足条件的最小的 (n) 一定是 (varphi(x')) 的约数。

    我们 (O(sqrt x)) 求出 (varphi(x)),再用 (O(sqrt {varphi(x)})) 算出答案即可。

    总时间复杂度为(O(T sqrt n))。问题解决。

    代码

    //Don't act like a loser.
    //This code is written by huayucaiji
    //You can only use the code for studying or finding mistakes
    //Or,you'll be punished by Sakyamuni!!!
    #include<bits/stdc++.h>
    #define int long long
    //忽略这个 @zdm
    using namespace std;
    
    int read() {
    	char ch=getchar();
    	int f=1,x=0;
    	while(ch<'0'||ch>'9') {
    		if(ch=='-')
    			f=-1;
    		ch=getchar();
    	}
    	while(ch>='0'&&ch<='9') {
    		x=x*10+ch-'0';
    		ch=getchar();
    	}
    	return f*x;
    } 
    
    int n;
    
    int qpow(int x,int y,int m) {
    	int ret=1;
    	while(y) {
    		if(y&1) {
    			ret=ret*x%m;
    		}
    		x=x*x%m;
    		y>>=1;
    	}
    	return ret;
    }
    int phi(int x) {
    	int ret=x;
    	for(int i=2;i*i<=x;i++) {
    		if(x%i==0) {
    			ret=ret/i*(i-1);
    		}
    		while(x%i==0) {
    			x/=i;
    		}
    	}
    	if(x>1) {
    		ret=ret/x*(x-1);
    	}
    	return ret;
    }
    
    int check(int x,int phix) {
    	int ans=x+1;
    	for(int i=1;i*i<=phix;i++) {
    		if(phix%i==0) {
    			if(qpow(10,i,x)==1) {
    				return i;
                    //若这个 i 满足条件一定是最优的
                    //直接返回
    			}
    			else if(qpow(10,phix/i,x)==1) {
    				ans=phix/i;
                    //否则要再取 min(直接更新即可,因为这个值单调减)
    			}
    		}
    	}
    	return ans==x+1? -1:ans;
    }
    
    signed main() {
    	//freopen(".in","r",stdin);
    	//freopen(".out","w",stdout);
    	
    	int t=read();
    	while(t--) {
    		int x=read();
    		if(x&1) {
    			x=x*9;//转换 x->x'
    		}
    		else {
    			x=x/2*9;
    		}
    		cout<<check(x,phi(x))<<endl;
    	}
    
    
    	//fclose(stdin);
    	//fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    Grunt 实现浏览器实时刷新
    Node环境搭建
    前端项目三方库管理
    Node项目包管理器
    前端开发利器
    面向对象目录
    Java 面向对象(十四)
    Java 面向对象(十三)
    Java 面向对象(十二)
    Java 面向对象(十)
  • 原文地址:https://www.cnblogs.com/huayucaiji/p/ABC222G.html
Copyright © 2011-2022 走看看