同余与模运算

1.同余与模运算

记得公式(a-b)mod n=[(a mod n)-(b mod n) +n]mod n;这里(a mod n)-(b mod n)可能小于0故要+n;

ab mod n=(long long) ( a mod n ) * ( b mod n ) mod n; 乘法结果可能溢出,所以要强制类型转换;

2.UVA上的10006题就用了这个技术;http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=947

题目大意,一个2<n<65000,如过对于每一个2<a<n-1,都有a^n mod n=a;并且a不是素数 那么a就是Carmichael number否则就是normal;

分析:这个题目,有两个条件(1)非素数;(2)满足同余表达式;故可用面向过程的想法,来分解这个题目

  1 // vsversion.cpp : 定义控制台应用程序的入口点。
  2 //
  3 
  4 #include "stdafx.h"
  5 
  6 /************************************************************************/
  7 /*首先构造素数表,然后每次读取一个数据,查表有的话normal;
  8 然后使用快速幂技术,a从2到n-1进行快速幂;如果过程中有值不符合,那么就normal
  9 否则就说是那种数; 
 10                                                                      */
 11 /************************************************************************/
 12 #include <cstdio>
 13 #include <iostream>
 14 #include <cstring>
 15 #include<cmath>
 16 using namespace std;
 17 #define MAX 65000
 18 int prime_list[MAX+10];
 19 void Init_prime_list(int n)
 20 {//找出小于n的所有素数;
 21 
 22     
 23     //使用去倍数法;
 24     memset(prime_list,-1,sizeof prime_list);
 25     for (int i=2;i*i<=n;i++)
 26     {
 27         for (int j=i*i;j<=n && prime_list[i]==-1;j+=i)
 28         {
 29             prime_list[j]=0;//非素数是1;
 30         }
 31     }
 32 
 33 }
 34 
 35 
 36 /*
 37 int pow_mod(int a,int n,int m)
 38 {
 39     if(n==1) return a%m;
 40     unsigned ans=pow_mod(a,n/2,m);
 41     ans=(ans*ans)%m;
 42     if(n%2==1) return ans*a%m;
 43     return ans;
 44 }*/
 45 int pow_mod(int a,int n,int m)
 46 {
 47     if (n==1)
 48         return a%m;
 49     unsigned  x=pow_mod(a,n/2,m);
 50     unsigned  ans=(x*x) %m;
 51     if (n%2==1)ans=(ans*a)%m;
 52     return (int)ans%m;
 53 }
 54 bool text(int n)
 55 {
 56     //首先判断是否是素数
 57     if (prime_list[n])
 58     {
 59         //cout<<n<<" is  normal.\n";
 60         return false;
 61     }
 62     //如果不是素数接着快速幂;
 63     for (int i=2;i<n;i++)
 64     {
 65         if (pow_mod(i,n,n)!=i)
 66             return false;
 67     }
 68     return true;
 69     
 70 }
 71 
 72 
 73 #ifndef ONLINE_JUDGE 
 74 int _tmain(int argc, _TCHAR* argv[])
 75 #else
 76 int main()
 77 //fstream cin("F://code//txt//33.txt");
 78 #endif
 79 //int main()
 80 {
 81     /*读取数据*/
 82     #ifndef ONLINE_JUDGE 
 83     freopen("F://code//txt//33.txt","r",stdin);
 84     //fstream cin("F://code//txt//33.txt");
 85     #endif
 86     //创建素数表;
 87     Init_prime_list(MAX);
 88     int n;
 89     cin>>n;
 90     while(n)
 91     {
 92         //memset(prime_list,0,sizeof prime_list);
 93         //进行检测//检测结果分析,做出决定;
 94         if (text(n))
 95         {
 96             //cout<<"The number "<<n<<" is a Carmichael number.\n";
 97            printf("The number %d is a Carmichael number.\n",n);
 98 
 99         }
100         else
101         {
102             //cout<<n<<" is normal.\n";
103             printf("%d is normal.\n",n);
104 
105         }
106         
107         
108         //读取下一个n;
109         cin>>n;
110     }
111     //system("pause");
112     return 0;
113 
114 }

 

 

  

转载于:https://www.cnblogs.com/dragonfive/archive/2013/04/29/3050897.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值