zoukankan      html  css  js  c++  java
  • 【洛谷P5431】【模板】乘法逆元2【乘法逆元】

    题目大意:

    题目链接:https://www.luogu.org/problem/P5431
    给定nn个正整数aia_i以及k,pk,p,定义它们在模pp意义下的乘法逆元为1aifrac{1}{a_i}
    i=1nkiaisum^{n}_{i=1}frac{k^i}{a_i}


    思路:

    这道题要在近O(n)O(n)的复杂度内求出nn个数字的逆元。那么我们来看一下逆元的定义。
    ab1(mod p)abequiv 1(mod p),则称aabb在模pp意义下的逆元。
    也就是说,在模pp意义下,aa的逆元即为1afrac{1}{a}
    那么我们设s[i]=Πj=1ia[j]s[i]=Pi^{i}_{j=1}a[j],然后设inv=1s[n]inv=frac{1}{s[n]},那么假设我们已经知道了Πj=1ia[j]Pi^{i}_{j=1}a[j]的逆元inviinv_i,那么显然有
    1ai1=invi×si1frac{1}{a_{i-1}}=inv_i imes s_{i-1}
    因为invi=1a1×a2×...×aninv_i=frac{1}{a_1 imes a_2 imes ... imes a_n}
    所以这样我们就可以在O(n)O(n)复杂度内求出所有数字的逆元。
    然后kik^i肯定是预处理的。这道题就解了。


    代码:

    #include <cstdio>
    #include <string>
    using namespace std;
    typedef long long ll;
    
    const int N=5000010;
    ll p,k,a[N],s[N],num[N];
    int n;
    
    ll read()
    {
    	ll d=0;
    	char ch=getchar();
    	while (!isdigit(ch)) ch=getchar();
    	while (isdigit(ch))
    		d=(d<<3)+(d<<1)+ch-48,ch=getchar();
    	return d;
    }
    
    ll power(ll x,ll m)
    {
    	ll ans=1;
    	for (;m;m>>=1,x=x*x%p)
    		if (m&1) ans=ans*x%p;
    	return ans;
    }
    
    int main()
    {
    	n=read(); p=read(); k=read();
    	num[0]=1;
    	s[0]=1;
    	for (int i=1;i<=n;i++)
    	{
    		num[i]=num[i-1]*k%p;
    		a[i]=read();
    		s[i]=s[i-1]*a[i]%p;
    	}
    	s[n]=power(s[n],p-2);
    	ll ans=0;
    	for (int i=n;i>=1;i--)
    	{
    		ans=(ans+s[i]*s[i-1]%p*num[i])%p;
    		s[i-1]=s[i]*a[i]%p;
    	}
    	printf("%lld",ans);
    	return 0;
    }
    
  • 相关阅读:
    ASP扫盲学习班第六课 添加新保存的数据
    三级联动菜单免刷新加载
    ASP按定制格式导出word文件的完美解决思路
    通用客户资源管理系统(客户资料保护库)
    SmR 通用信息采集系统(新闻小偷)
    ASP扫盲学习班第三课 程序界面的设计
    我的新作品(单身贵族网全站)
    《将博客搬至CSDN》
    我的新作品
    asp函数大全
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998070.html
Copyright © 2011-2022 走看看