zoukankan      html  css  js  c++  java
  • hdu 1395 2^x mod n = 1

    点击打开链接

    显然没有解的时候是n==1||n%2==0

    做法要利用这样几个定理:

    第一个是a^phi(m)%m=1

    这个等式在m和a互质的时候一定成立

    在这个题目中,因为a=2

    所以m与a不互质,除非m为偶数

    当然m=1的时候需要特殊处理下,这些都是小问题。

     

    现在这个问题明了了,即在m为奇数(大于1)的时候一定有解。

    那么就有人萌生了直接暴力的方法。当然对于这个题,直接暴力是可以的,我最先开始也是这样过的

    但是今天重新做了一下这个题我仔细的思考了一下,发现果然有更加巧妙的方法来解决该类问题。

    首先说暴力的缺点吧,大多数情况暴力其实还是非常快的,但是如果当m为一个非常大的质数,那么问题就严重了。因为质数的欧拉函数就是质数-1

    那么也就是说,最坏情况下,我们可能要枚举很多次才能找到一个解

     

    那么更为高效的方法是:把m的欧拉函数值,假设值为phi进行质因数分解

    然后依次枚举phi的每一个因子,同时判断这个因子x是否满足2^x%m==1,不断更新一个最小值,最后得到答案。

    那么为什么这样做就是对的呢?

    首先需要知道:

    a^x%m==1满足这个方程的最小x称为a对模m的指数。我们记做ordm(a),如果ordm(a)==phi(m)则我们称a为模m的原根

    有:a^X%m==1    <-===->    ordm(a)整除X

    根据以上所说:a^phi(m)=1成立,那么phi(m)%ordm(a)==0也是成立的

    所以ordm(a)就是phi的一个因子

    所以分解phi然后枚举phi的因子的做法是正确的

    #include"stdio.h"
    int main()
    {
    	int s,n,i,cnt;
    	while(scanf("%d",&n)!=EOF)
    	{
    		cnt=0;
    		if(n%2==0||n==1)
    			printf("2^? mod %d = 1\n",n);
    		else
    		{
    			cnt=1;s=2;
    			while(s!=1)
    			{
    				cnt++; 
    				s=((s*2)%n);
    			}
    			printf("2^%d mod %d = 1\n",cnt,n);
    		}
    	}
    	return 0;
    }



  • 相关阅读:
    Leetcode 16.25 LRU缓存 哈希表与双向链表的组合
    Leetcode437 路径总和 III 双递归与前缀和
    leetcode 0404 二叉树检查平衡性 DFS
    Leetcode 1219 黄金矿工 暴力回溯
    Leetcode1218 最长定差子序列 哈希表优化DP
    Leetcode 91 解码方法
    Leetcode 129 求根到叶子节点数字之和 DFS优化
    Leetcode 125 验证回文串 双指针
    Docker安装Mysql记录
    vmware虚拟机---Liunx配置静态IP
  • 原文地址:https://www.cnblogs.com/yyf573462811/p/6365257.html
Copyright © 2011-2022 走看看