數論四大定理小結(初級)
阿新 • • 發佈:2019-02-18
回顧:
數論四大定理
威爾遜定理若p為質數,則p可整除(p-1)!+1。
尤拉定理(也稱費馬-尤拉定理)若n,a為正整數,且n,a互素,(a,n) = 1,則
a^φ(n) ≡ 1 (mod n)
孫子定理(又稱中國剩餘定理)公元前後的《孫子算經》中有“物不知數”問題:“今有物不知其數,三三數之餘二 ,五五數之餘三 ,七七數之餘二,問物幾何?”答為“23”。
明朝程大位用歌謠給出了該題的解法:“三人同行七十稀,五樹梅花廿一枝,七子團圓月正半,除百零五便得知。”
以現代的說法,是找出三個關鍵數70,21,15。解法的意思就是用70乘3除所得的餘數,21乘5除所得的餘數,15乘7除所得的餘數,然後總加起來,除以105的餘數就是答案。
假如p是質數,且(a,p)=1,那麼 a^(p-1) ≡1(mod p)。
假如p是質數,且a,p互質,那麼 a的(p-1)次方除以p的餘數恆等於1。
1.威爾遜定理 HDU 2973 YAPTCHA
這題就是威爾遜定理的一個簡單應用,由於向下取整的存在,式子的值就‘0’或‘1’。
#include<iostream> #include<cmath> #include<cstring> #include<string> #include<algorithm> #include<iomanip> #include<cstdio> using namespace std; inline void RD(int &ret) { char c; do { c=getchar(); } while(c<'0'||c>'9'); ret=c-'0'; while((c=getchar())>='0'&&c<='9') { ret=ret*10+(c-'0'); } } inline void OT(int a) { if(a>=10) { OT(a/10); } putchar(a%10+'0'); } bool f(int x) { int i,n=int(sqrt(double(x))); if(x==2||x==3) { return true; } for(i=2;i<=n;++i) { if(x%i==0) { return false; } } return true; } int a[1000001]; void g() { int i; a[1]=0; for(i=2;i<=1000000;++i) { if(f(3*i+7)==true)//判斷是否為素數,而確定前式是否為整除式 { a[i]=a[i-1]+1; } else { a[i]=a[i-1]; } } } int main() { int t,n,i; g(); RD(t); while(t--) { RD(n); OT(a[n]); printf("\n"); } return 0; }
2.尤拉定理 HDU 1395 2^x mod n = 1
尤拉定理的直接應用,求出n以內與n互質的數量
3.孫子定理 HDU 3579 Hello Kiki#include<iostream> #include<cmath> #include<cstring> #include<string> #include<algorithm> #include<iomanip> #include<cstdio> using namespace std; inline void RD(int &ret) { char c; do { c=getchar(); } while(c<'0'||c>'9'); ret=c-'0'; while((c=getchar())>='0'&&c<='9') { ret=ret*10+(c-'0'); } } inline void OT(int a) { if(a>=10) { OT(a/10); } putchar(a%10+'0'); } int main() { int n,sum,i; while(scanf("%d",&n)!=EOF) { if(n==1||n%2==0) { printf("2^? mod %d = 1\n",n); } else { sum=1; for(i=1;i<5001;++i)//求互質數 { sum*=2; sum%=n; if(sum==1) { break; } } printf("2^%d mod %d = 1\n",i,n); } } return 0; }
孫子定理的一般應用,由於存在不可能的情況,所以不建議使用直接暴搞,應使用擴充套件歐幾里得公式,求出初等公式,在一步步求解。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
using namespace std;
inline void RD(int &ret)
{
char c;
do
{
c=getchar();
}
while(c<'0'||c>'9');
ret=c-'0';
while((c=getchar())>='0'&&c<='9')
{
ret=ret*10+(c-'0');
}
}
inline void OT(int a)
{
if(a>=10)
{
OT(a/10);
}
putchar(a%10+'0');
}
int ext_gcd(int a,int b,int& x,int& y)//擴充套件歐幾里德
{
int t,ret;
if (!b)
{
x=1,y=0;
return a;
}
ret=ext_gcd(b,a%b,x,y);
t=x,x=y,y=t-a/b*y;
return ret;
}
int main()
{
int i,t,n,cas=0,f,m1,m2,a1,a2,z,x,y,j,m[11],a[11];
RD(t);
while(t--)
{
cas++;
RD(n);
for(i=0; i<n; i++)
{
RD(m[i]);
}
for(i=0; i<n; i++)
{
RD(a[i]);
}
f=0;
m1=m[0];
a1=a[0];
for(i=1; i<n; i++)//求遞推式
{
m2=m[i];
a2=a[i];
z=ext_gcd(m1,m2,x,y);
if((a2-a1)%z)
{
f=1;
break;
}
j=m2/z;
x=(x*(a2-a1))/z;
x=(x%j+j)%j;
a1=m1*x+a1;
m1=(m1*m2)/z;
a1=(a1%m1+m1)%m1;
}
if(f==1)
{
a1=-1;
}
if(a1==0&&n>1)
{
a1=m1;
}
if(a1==0&&n==1)
{
a1=m[0];
}
printf("Case %d: %d\n",cas,a1);
}
return 0;
}
4.費馬小定理 HDU 4196 Remoteland
一道費馬小定理的變型題,要求n以內包括n的數相乘組成一個最大的完全平方數,需要先通過唯一分解定理將N!(必為最大)分解為質因數的相應次冪相乘,由於要得到的是完全平方數,所以需要除去次冪數為奇數的質因數(除1次)。最後可以轉化為MAX(n)=(n!*b^(mod-2))%mod。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#define N 1000000007
#define M 10000001
using namespace std;
__int64 b[M];
int a[M],m;
inline void RD(int &ret)
{
char c;
do
{
c=getchar();
}
while(c<'0'||c>'9');
ret=c-'0';
while((c=getchar())>='0'&&c<='9')
{
ret=ret*10+(c-'0');
}
}
inline void OT(int a)
{
if(a>=10)
{
OT(a/10);
}
putchar(a%10+'0');
}
void f()//求N!,求質因數表
{
int i,j;
b[0]=1;
for(i=1;i<M;++i)
{
b[i]=b[i-1]*i%N;
}
int x=sqrt(M*1.0);
for(i=2;i<=x;++i)
{
if(!a[i])
{
for(j=i*i;j<M;j+=i)
{
a[j]=1;
}
}
}
for(i=2;i<M;++i)
{
if(!a[i])
{
a[m++]=i;
}
}
}
__int64 p(__int64 x,__int64 y)//快速冪取模
{
__int64 res=1;
while(y>0)
{
if(y%2==1)
{
res=(res*x)%N;
}
x=(x*x)%N;
y/=2;
}
return res;
}
int main()
{
f();
int n,i,tmp,tsp;
__int64 ans,sum;
while(scanf("%d",&n))
{
if(n==0)
{
break;
}
sum=1;
for(i=0;i<m&&a[i]<=n;++i)
{
tmp=n;
tsp=0;
while(tmp)
{
tsp+=(tmp/=a[i]);
}
if(tsp%2==1)
{
sum=sum*a[i]%N;
}
}
ans=b[n]*p(sum,N-2)%N;//費馬小定理
printf("%I64d\n",ans);
}
return 0;
}
陸續還有總結,敬請期待~