CSP-S模板-数论
模版来源于洛谷CSP-S模版赛
P3811 【模板】模意义下的乘法逆元
题意
对于 \(1 \sim n\) 中每个数,找到一个 \(x\) 满足 \(ax \equiv 1 \pmod{p}\)
引入:费马小定理/欧拉定理
费马小定理
若正整数 \(p\) 为质数,且正整数 \(a\) 不为 \(p\) 的倍数,则有 \(a^{p-1} \equiv 1 \pmod{p}\)
欧拉定理
若正整数 \(a\) 与 \(n\) 互质,则 \(a^{\phi(n)} \equiv 1 \pmod{n}\),其中 \(\phi(n)\) 为欧拉函数,表示小于 \(n\) 且与 \(n\) 互素的正整数个数。
不难看出,欧拉定理是费马小定理的扩展
费马小定理的证明
考虑构造集合 \(T=\{a\cdot 1,\,a\cdot 2,\,\dots,\,a\cdot(p-1)\}\)
-
证明其中任意两数模 \(p\) 不同余
假设存在 \(1 \le i < j \le p-1\),使得 \(ai \equiv aj \pmod{p}\)
则有\(a(j-i) \equiv 0 \pmod{p}\)
由于 \(a\) 与 \(p\) 互质,且 \(0< j-i<p\) 不是 \(p\) 的倍数,那么 \(a(j-i)\) 不为 \(p\) 的倍数,矛盾
所以 \(T\) 中元素模 \(p\) 两两不同余 -
\(T\)是模 \(p\) 的剩余简化系
懒得认真证了,感性理解一下
就是集合里一共 \(p-1\) 个数,然后因为两两模 \(p\) 不同余所以模 \(p\) 有 \(p-1\) 种取值,那就只能一一对应了 -
相乘
\((a\cdot 1)\cdot (a\cdot 2)\cdots (a\cdot (p-1)) \equiv 1\cdot 2\cdots (p-1) \pmod{p}\)
\(a^{p-1}\cdot(p-1)! \equiv (p-1)! \pmod{p}\)
因为 \(\gcd((p-1)!,p)=1\)
所以两边同时消去 \((p-1)!\)
\(a^{p-1} \equiv 1 \pmod{p}\)
证毕
欧拉定理的证明
虽然我并不认为这个东西人类能看懂
做法
这个题对于每一个数按照费马小定理套快速幂跑一遍显然会T飞,考虑线性递推
我们令 \(jc[i] = i!\),\(jcn[i]=\frac{1}{i!}\)
\(jcn[i+1]=\frac{1}{(i+1)!}\)
\(jcn[i+1]\times(i+1)=\frac{1}{i!}\)
\(jcn[i+1]\times(i+1)=jcn[i]\)
递推求出 \(jcn\) 后,\(\frac{1}{i}=jcn[i]\times jc[i-1]\)
代码
#include<bits/stdc++.h>
#define int long long
#define ll long long
#define int128 __int128
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3fll
#define finf 0xcfcfcfcf
#define FINF 0xcfcfcfcfcfcfcfcf
#define endl '\n'
#define lowbit(x) (x & -x)
#define ls (u<<1)
#define rs (u<<1|1)
#define eps 1e-9
#define mem(x) memset(x,0x3f,sizeof(x));
#define fmem(x) memset(x,0xcf,sizeof(x));
using namespace std;
const int maxn=3e6+5;
const int maxm=3e6;
//const int mod=998244353;
int n,m,x,y,t,mod;
int pw(int a,int b){
int ans=1;
while(b){
if(b&1)ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
int jc[maxn],jcn[maxn];
void init(){
jc[0]=1;
for(int i=1;i<=n;i++)jc[i]=jc[i-1]*i%mod;
jcn[n]=pw(jc[n],mod-2);
for(int i=n-1;i>=0;i--)jcn[i]=jcn[i+1]*(i+1)%mod;
return ;
}
signed main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin>>n>>mod;
init();
for(int i=1;i<=n;i++)cout<<jcn[i]*jc[i-1]%mod<<endl;
return 0;
}
后记&吐槽
神秘证明要写成 LaTeX 写我半小时
这个题要注意 \(n\) 和 \(p\) 并不在一个数量级,但实际上只用递推到 \(n\) 就行,推到 \(p\) 会 MLE
P1495 【模板】中国剩余定理(CRT)/ 曹冲养猪
题意
\(\begin{cases} x \equiv a_1 \pmod{m_1}\\ x \equiv a_2 \pmod{m_2}\\ \vdots\\ x \equiv a_k \pmod{m_k} \end{cases} \)
\(m_1 , m_2 ,\dots, m_k\) 之间两两互质
求满足所有式子的整数 \(x\);解在 \(M=\prod m_i\) 下唯一
总结一下就是:找一个数 \(x\),它除以 \(m_1\) 余 \(a_1\)、除以 \(m_2\) 余 \(a_2,\dots\),求这个 \(x\)。
做法
- 中国剩余定理 (CRT)
- 扩展欧几里得定理 (exgcd)
证明
略 之后再补吧打个费马小定理的证明都快打死了
代码
#include<bits/stdc++.h>
#define int long long
#define ll long long
#define int128 __int128
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3fll
#define finf 0xcfcfcfcf
#define FINF 0xcfcfcfcfcfcfcfcf
#define endl '\n'
#define lowbit(x) (x & -x)
#define ls (u<<1)
#define rs (u<<1|1)
#define eps 1e-9
#define mem(x) memset(x,0x3f,sizeof(x));
#define fmem(x) memset(x,0xcf,sizeof(x));
using namespace std;
const int maxn=2e5+5;
const int maxm=1e6;
const int mod=998244353;
int n,m,x,y,t;
int pw(int a,int b){
int ans=1;
while(b){
if(b&1)ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
// int ans=1;
// while(b){
// if(b&1)ans=ans*a;
// a=a*a;
// b>>=1;
// }
return ans;
}
//int jc[maxn],jcn[maxn];
//void init(){
//
// jc[0]=1;
// for(int i=1;i<=maxm;i++)jc[i]=jc[i-1]*i%mod;
//
// jcn[maxm]=pw(jc[maxm],mod-2);
// for(int i=maxm-1;i>=0;i--)jcn[i]=jcn[i+1]*(i+1)%mod;
//
// return ;
//}
int a[maxn],b[maxn];
int128 M=1;
int ans=0;
void exgcd(int a,int b,int &l,int &r){
if(b==0){
l=1,r=0;
return ;
}
int x,y;
exgcd(b,a%b,x,y);
l=y,r=x-a/b*y;
return ;
}
signed main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i]>>b[i],M*=a[i];
for(int i=1;i<=n;i++){
int128 u=M/a[i];x=0;y=0;
exgcd(u,a[i],x,y);
x=(x%a[i]+a[i])%a[i];
ans+=b[i]*u%M*x%M;
ans%=M;
}
cout<<ans<<endl;
return 0;
}

浙公网安备 33010602011771号