逆元,摘自
SssssssBbbbbbbb
on求出1~n 的逆元
#include<bits/stdc++.h>
using namespace std;
int mod=17,inv[30];
void init()
{
inv[1]=1;
for(int i=2;i<=20;i++)
inv[i]=((mod-mod/i)*inv[mod%i])%mod;
}
void output()
{
for(int i=1;i<=20;i++)
cout<<inv[i]<<" ";
}
int main()
{
init();
output();
return 0;
}
费马小定理求逆元 摘自guhaiteng
逆元模板题 hdu1576
Problem Description
要求(A/B)%9973,但由于A很大,我们只给出n(n=A%9973)(我们给定的A必能被B整除,且gcd(B,9973) = 1)。
Input
数据的第一行是一个T,表示有T组数据。
每组数据有两个数n(0 <= n < 9973)和B(1 <= B <= 10^9)。
每组数据有两个数n(0 <= n < 9973)和B(1 <= B <= 10^9)。
Output
对应每组数据输出(A/B)%9973
Sample Input
2 1000 53 87 123456789
Sample Output
7922 6060
#include<bits/stdc++.h>
#define int long long
using namespace std;
int b,a;
void exgcd(int a,int b,int &d,int &x,int &y)
{
if(!b)d=a,x=1,y=0;
else exgcd(b,a%b,d,y,x),y-=(a/b)*x;
}
int inv(int a,int n)
{
int d,x,y;
exgcd(a,n,d,x,y);
return d==1?(x+n)%n:-1;
}
main()
{
int n;
cin>>n;
while(n--)
{
cin>>a>>b;
int x=inv(b,9973);
printf("%lld\n",(a*x)%9973);
}
return 0;
}
线段树HDU5475
搜过来的题目试求逆元,但是细想发现不对劲,因为你除再取mod是不可以的(可以想一下为什么),于是我就不知道怎么做了,看了网上的题解神奇的发现是线段树???然后单点更新,维护乘积就可以了。。
写的时候不知道scanf %lld为什么萎了,然后就用cin水过去了。。本以为会卡时间。。
#include<bits/stdc++.h>
#define mid (l+(r-l)/2)
#define ls (rt<<1)
#define rs (rt<<1|1)
#define int long long
using namespace std;
int tr[500000<<2],n,t,mod,t1,t2;
void build(int l,int r,int rt)
{
tr[rt]=1;if(l==r) return ;
build(l,mid,ls),build(mid+1,r,rs);
}
void update(int l,int r,int rt,int L,int C)
{
if(l==r){tr[rt]=C;return ;}
if(L<=mid) update(l,mid,ls,L,C);
else update(mid+1,r,rs,L,C);
tr[rt]=(tr[ls]*tr[rs])%mod;
}
main()
{
scanf("%lld",&t);
for(int kkk=1;kkk<=t;kkk++)
{
printf("Case #%lld:\n",kkk);
cin>>n>>mod;
build(1,n,1);
for(int i=1;i<=n;i++)
{
scanf("%lld%lld",&t1,&t2);
if(t1==1) update(1,n,1,i,t2);
if(t1==2) update(1,n,1,t2,1);
cout<<tr[1]%mod<<"\n";
}
}
return 0;
}
欧拉定理的证明
摘自网络
欧拉函数
不写了,见我之前的博客。
费马小定理
a是不能被质数p整除的正整数,则有a^(p-1) ≡ 1 (mod p)
证明这个定理非常简单,由于φ(p) = p-1,代入欧拉定理即可证明。
同样有推论:对于不能被质数p整除的正整数a,有a^p ≡ a (mod p)
hdu1395暴力水过了。。正解快速幂,欧拉函数
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
while(cin>>n)
{
if(n==1||!(n&1))
{printf("2^? mod %d = 1\n",n); continue;}
for(int j=1,mi=2;;mi<<=1,j++,mi%=n)
if(mi%n==1)
{
printf("2^%d mod %d = 1\n",j,n);
break ;
}
}
return 0;
}
正解
#include<bits/stdc++.h>
#define int __int64
using namespace std;
int tt[2000],mod,cnt;
int phi(int n)
{
int m=(int)sqrt(n+0.5),ans=n;
for(int i=2;i<=m;i++)
{
if(n%i==0)
{
ans=ans/i*(i-1);
while(n%i==0) n/=i;
}
}
if(n>1) ans=ans/n*(n-1);
return ans;
}
void find(int n)
{
int m=(int) sqrt(n+0.5);
tt[++cnt]=n;
for(int i=2;i<=m;i++)
{
if(i*i==n) tt[++cnt]=i;
else if(n%i==0) tt[++cnt]=i,tt[++cnt]=n/i;
}
}
int Pow(int n,int k)//×¢Òâ´óд·ñÔò»á³åÍ»
{
int ans=1;
while(k)
{
if(k&1) ans=(ans*n)%mod;
n=(n*n)%mod,k>>=1;
}
return ans%mod;
}
main()
{
int n;
while(cin>>n)
{
if(n==1||!(n&1))
{cout<<"2^? mod "<<n<<" = 1"<<endl;continue;}
int m=phi(n),ans=0;
cnt=0,find(m),mod=n;
sort(tt+1,tt+1+cnt);
for(int i=1;i<=cnt;i++)
{
if(Pow(2,tt[i])==1)
{ans=tt[i];break;}
}
cout<<"2^"<<ans<<" mod "<<n<<" = 1"<<endl;
}
return 0;
}