【乘法逆元】好题选讲

目录

1.Luogu P2613【模板】有理数取余
2.POJ 1845Sumdiv
3.Luogu P2155沙拉公主的困惑(线性求逆)

一、【模板】有理数取余

题目:

求 a / b m o d 19260817 求a/bmod19260817 a/bmod19260817

题解:

板子题没什么好说的
a b = a ∗ i n v ( b ) \frac{a}{b}=a*inv(b) ba=ainv(b)
输入太大,输的时候边读边取模就可以辣

#include<bits/stdc++.h>
#define ll long long 
using namespace std;
ll a,b,mod=19260817;
inline ll read()
{
	ll ans=0;char s=getchar();
	while(s>'9'||s<'0')s=getchar();
	while(s>='0'&&s<='9')
	{
		ans=((ans<<1)%mod+(ans<<3)%mod+(s&15))%mod;
		s=getchar();
	}return ans;
}
ll quick_m(ll i,ll n)
{
	i%=mod;
	ll ans=1,ds=i;
	while(n)
	{
		if(n&1)
		{
			ans=ans*ds%mod;
		}
		ds=ds*ds%mod;
		n>>=1;
	}return ans%mod;
}
signed main(){
	a=read();b=read();
	if(b==0){printf("Angry!");return 0;}
	printf("%lld",a*quick_m(b,mod-2)%mod);
	return 0;
}

二、 Sumdiv

题目:

a b 的 约 数 和 m o d   9901 a^b的约数和mod \ 9901 abmod 9901

题解:

若a的唯一质因数分解为 a = p 1 k 1 p 2 k 2 p 3 k 3 . . . p n k n a=p_1^{k_1}p_2^{k_2}p_3^{k_3}...p_n^{k_n} a=p1k1p2k2p3k3...pnkn
a b a^b ab的唯一质因数分解为 a b = p 1 k 1 b p 2 k 2 b p 3 k 3 b . . . p n k n b a^b=p_1^{k_1b}p_2^{k_2b}p_3^{k_3b}...p_n^{k_nb} ab=p1k1bp2k2bp3k3b...pnknb
约数和数学表达
s = ( 1 + p 1 + p 1 2 . . . + p 1 k 1 b ) ( 1 + p 2 + p 2 2 . . . + p 2 k 2 b ) . . . ( 1 + p n + p n 2 . . . + p n k n b ) s=(1+p_1+p_1^2...+p_1^{k_1b})(1+p_2+p_2^2...+p_2^{k_2b})...(1+p_n+p_n^2...+p_n^{k_nb}) s=(1+p1+p12...+p1k1b)(1+p2+p22...+p2k2b)...(1+pn+pn2...+pnknb)
等比数列求解
s = ( p 1 k 1 b + 1 − 1 p 1 − 1 ) ( p 2 k 2 b + 1 − 1 p 2 − 1 ) . . . ( p n k n b + 1 − 1 p n − 1 ) s=(\frac{p_1^{k_1b+1}-1}{p_1-1})(\frac{p_2^{k_2b+1}-1}{p_2-1})...(\frac{p_n^{k_nb+1}-1}{p_n-1}) s=(p11p1k1b+11)(p21p2k2b+11)...(pn1pnknb+11)
我们逆元+快速幂?
不, p i − 1 可 能 为 9901 的 倍 数 , 不 与 9901 互 质 , 此 时 没 有 逆 元 pi-1可能为9901的倍数,不与9901互质,此时没有逆元 pi199019901
那怎么办?
这里有个非常nice 的idea,上图
若 求 a b ( m o d   p ) , 且 刚 好 有 a 为 b 的 倍 数 若求\frac a b (mod \ p ),且刚好有a为b的倍数 ba(mod p),ab
在这里插入图片描述
注意:有多组数据。。。还有快速幂时可能会爆long long,用龟速乘。
卡在RE的应该不止我一个吧(现已解决,a>1卡了几乎两页)

#include<iostream>
#include<string.h>
#include<stdio.h>
#define ll long long
using namespace std;
ll qk_c(ll a,ll b,ll mod)
{
	ll ans=0;a%=mod;
	while(b)
	{
		if(b&1)
		{
			ans=(ans+a)%mod;
		}
		a=(a+a)%mod;
		b>>=1;
	}
	return ans;
}
ll qk_m(ll a,ll k,ll mod)
{
	ll ans=1;a%=mod;
	while(k)
	{
		if(k&1)
		{
			ans=qk_c(ans,a,mod);
		}
		a=qk_c(a,a,mod);
		k>>=1;
	}
	return ans;
}
const int N=10005;
int z[N],p;
bool vis[N];
void init()
{
	for(int i=2;i<N;i++)
	{
		if(!vis[i])z[++p]=i;
		for(int j=1;j<=p&&i*z[j]<N;j++)
		{
			vis[i*z[j]]=1;
			if(i%z[j]==0)break;
		}
	}
}
const int mod=9901;
ll a,b,ans;
int k;
int main()
{ 
	init();
	while(cin>>a>>b)
	{
		ans=1;
		for(int i=1;i<=p&&z[i]*z[i]<=a;i++)
		{
			if(a%z[i]==0)
			{
				k=0;while(a%z[i]==0)a/=z[i],k++;
				ll M=mod*(z[i]-1);
				ans*=(qk_m(z[i],k*b+1,M)+M-1)/(z[i]-1);
				ans%=mod;
			}
		}
		if(a>1)
		{
			ll M=mod*(a-1);
			ans*=(qk_m(a,b+1,M)+M-1)/(a-1);
			ans%=mod;
		}
		cout<<ans<<endl;
	}
    return 0;
}

三、沙拉公主的困惑

题目:

1 − > N ! 1->N! 1>N!中与 M ! M! M!互质的个数

题解:

推演一下,最后得 N ! M ! ϕ ( M ! ) \frac {N!}{M!} \phi{(M!)} M!N!ϕ(M!)
=> N ! ( 1 − p 1 p 1 ) ( 1 − p 2 p 2 ) . . . ( 1 − p k p k ) N!(\frac {1-p_1}{p_1})(\frac {1-p_2}{p_2})...(\frac {1-p_k}{p_k}) N!(p11p1)(p21p2)...(pk1pk)
一堆预处理,质数+线性求逆+阶乘。。。

#include<bits/stdc++.h>
#define ll long long 
using namespace std;
inline ll read()
{
	ll ans=0;char s=getchar();
	while(!isdigit(s))s=getchar();
	while(isdigit(s))
	{
		ans=(ans*10)+(s&15);
		s=getchar();
	}return ans;
}
const int N=1e7+10;
int T;
ll n,m,mod;
int z[N],p;
bool vis[N];
void get_prime()
{
	for(int i=2;i<N;i++)
	{
		if(!vis[i])z[++p]=i;
		for(int j=1;j<=p&&i*z[j]<N;j++)
		{
			vis[i*z[j]]=1;
			if(i%z[j]==0)break;
		}
	}
}
ll inv[N],mul[N],pt[N];
int main()
{
	scanf("%d%lld",&T,&mod);
	get_prime();
	inv[1]=1;inv[0]=1;
	for(int i=2;i<N;i++)
		inv[i]=inv[mod%i]*(mod-mod/i)%mod;
	mul[1]=1;
	for(int i=2;i<N;i++)
		mul[i]=mul[i-1]*i%mod;
	pt[1]=1;
	for(int i=2;i<N;i++)
		if(!vis[i])
			 pt[i]=pt[i-1]*(i-1)%mod*inv[i%mod]%mod;
		else pt[i]=pt[i-1];
	while(T--)
	{
		n=read();m=read();
		printf("%lld\n",mul[n]*pt[m]%mod);
	}
}//假装没开O2就过了
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值