1. 程式人生 > >洛谷 P1082 同余方程

洛谷 P1082 同余方程

我不知道 dal long das 同余 art 不知道 ++ cloc

題目描述

求關於 x 的同余方程 ax ≡ 1 (mod b)的最小正整數解。

輸入輸出格式

輸入格式:

輸入只有一行,包含兩個正整數 a, b,用一個空格隔開。

輸出格式:

輸出只有一行,包含一個正整數 x0,即最小正整數解。輸入數據保證一定有解。

輸入輸出樣例

輸入樣例#1:
3 10
輸出樣例#1:
7

說明

【數據範圍】

對於 40%的數據,2 ≤b≤ 1,000;

對於 60%的數據,2 ≤b≤ 50,000,000;

對於 100%的數據,2 ≤a, b≤ 2,000,000,000。

NOIP 2012 提高組 第二天 第一題

//智商太低,搞這個搞了一晚上……

解題思路

  我太菜了,不會擴歐,用的是dalao教的費馬小定理,但這題沒規定b一定是質數,所以要用歐拉定理,費馬小定理其實就是歐拉定理的特殊情況。

    1、同余的傳遞性。

    若$$a \equiv b\mod p $$    且$$b \equiv c\mod p $$    則$$ a \equiv c\mod p$$

    2、歐拉定理(同余的那個)$$a^{\phi(b)} \equiv 1\mod b$$

    3、題目要求的那個式子$$ax \equiv 1\mod b$$

  以上三項代換一下得到$ax \equiv a^{\phi(b)} \mod{b}$,我不知道為什麽左邊的a可以除過去——$x \equiv a^{\phi(b)-1}\mod b$,於是最小的x就是$a^{\phi(b)-1}\mbox{%} b$。

源代碼

#include<stdio.h>
#include<time.h>
#include<math.h>
#include<algorithm>
#include<cstring>
#define ll long long
long long phi(long long n)
{
    ll res=n,now=n,max=ceil(sqrt(n));
    int b[max+1],size=0;ll prime[max/2];
    memset(b,1,sizeof(b));b[1]=0;
    
for(int i=2;i<=max;i++){//不篩素數表會TLE一個點,本機要跑44s…… if(b[i]==0) continue; size++;prime[size]=i; for(int t=2*i;t<=max;t+=i) b[t]=0; } for(int i=1;i<=size;i++){ if(now%prime[i]==0){ res=res/prime[i]*(prime[i]-1); while(now%prime[i]==0){ now/=prime[i]; } } if(now==1) break; } if(now!=1) res=res/now*(now-1); return res; } long long p(long long n,long long k,long long mo) { if(k==0) return 1; if(k==1) return n%mo; long long a=p(n,k>>1,mo)%mo; a=a*a%mo; //printf("%lld %lld\n",k,a); return a*p(n,k&1,mo)%mo; } int main() { //freopen("mod.in","r",stdin); //freopen("mod.out","w",stdout);//cogs的印記…… long long a,b; //double start=clock(); scanf("%lld%lld",&a,&b); long long k=phi(b)-1; //printf("%lf\n",(clock()-start)/1000000); printf("%lld\n",(p(a,k,b)+b)%b); return 0; }

洛谷 P1082 同余方程