洛谷 P5431 【模板】模意义下的乘法逆元 2

对于本题建议先观看洛谷 P3811 【模板】模意义下的乘法逆元 、 乘法逆元 - OI Wiki 和 洛谷 P3811 【模板】模意义下的乘法逆元-CSDN博客 的讲解。

题目描述

给定 𝑛 个正整数 𝑎𝑖 ,求它们在模 𝑝 意义下的乘法逆元。

由于输出太多不好,所以将会给定常数 𝑘,你要输出的答案为:

\sum_{n}^{i=1}\frac{k^i}{a[i]}

答案对 𝑝 取模。

输入格式

第一行三个正整数 𝑛,𝑝,𝑘意义如题目描述。
第二行 𝑛 个正整数 𝑎𝑖是你要求逆元的数。

输出格式

输出一行一个整数,表示答案。

输入输出样例

输入 #1复制

6 233 42
1 4 2 8 5 7

输出 #1复制

91

说明/提示

对于 30% 的数据,1≤𝑛≤1e5

对于 100% 数据,1≤𝑛≤5×1e6,2≤𝑘<𝑝≤1e9,1≤𝑎𝑖<𝑝,保证 𝑝 为质数。

提示:本题时间限制较为严格,请注意使用较快的 IO 方式。

看了以上讲解,应该知道答题思路了;

我们可以根据以前的思路写出代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,p,k,fac[5000005],inv[5000005],ans,x[5000005];
int binpow(int a,int b)
{
    int res=1;
    while(b)
    {
        if(b&1)
        {
            res*=a;
            res%=p;
        }
        a*=a;
        a%=p;
        b>>=1;
    }
    return res;
}
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    cin>>n>>p>>k;
    int sb=k;
    fac[0]=1;
    for(int i=1;i<=n;++i)
    {
        cin>>x[i];
    }
	for(int i=1;i<=n;++i)
	{
		fac[i]=fac[i-1]*x[i];
		fac[i]%=p;
	}
	inv[n]=binpow(fac[n],p-2);
	for(int i=n-1;i>=1;--i)
	{
		inv[i]=inv[i+1]*x[i+1]%p;
	}
	for(int i=1;i<=n;++i)
	{
		ans+=fac[i-1]*inv[i]%p*k;
        ans%=p;
        k*=sb;
        k%=p;
	}
    cout<<ans;

    return 0;
}

但是你会发现,这样的代码依然会TLE,你可能就非常的疑惑,但是如果你在读一遍题,你会发现,有一句话是这么写的:提示:本题时间限制较为严格,请注意使用较快的 IO 方式。

所以这个题目读入要使用快读,输出使用printf或cout快速优化,(最好使用printf);

所以我把我的快读模版给大家:

inline int read(){
	int n=0,x=1;char c;
	for(c=getchar();c<'0'||c>'9';c=getchar())
		if(c=='-')x=-1;else x=1;
	for(;c>='0'&&c<='9';c=getchar())
		n=(n<<3)+(n<<1)-'0'+c;
	return x*n;
}

这样我们就可以写出AC代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
inline int read(){
	int n=0,x=1;char c;
	for(c=getchar();c<'0'||c>'9';c=getchar())
		if(c=='-')x=-1;else x=1;
	for(;c>='0'&&c<='9';c=getchar())
		n=(n<<3)+(n<<1)-'0'+c;
	return x*n;
}
int n,p,k,fac[5000005],inv[5000005],ans,x[5000005];
int binpow(int a,int b)
{
    int res=1;
    while(b)
    {
        if(b&1)
        {
            res*=a;
            res%=p;
        }
        a*=a;
        a%=p;
        b>>=1;
    }
    return res;
}
signed main()
{
    //ios::sync_with_stdio(0);使用getchar()和printf最好关闭cin快速优化
    //cin.tie(0);cout.tie(0);
    n=read(),p=read(),k=read();
    int sb=k;
    fac[0]=1;
    for(int i=1;i<=n;++i)
    {
        x[i]=read();
    }
	for(int i=1;i<=n;++i)
	{
		fac[i]=fac[i-1]*x[i];
		fac[i]%=p;
	}
	inv[n]=binpow(fac[n],p-2);
	for(int i=n-1;i>=1;--i)
	{
		inv[i]=inv[i+1]*x[i+1]%p;
	}
	for(int i=1;i<=n;++i)
	{
		ans+=fac[i-1]*inv[i]%p*k;
        ans%=p;
        k*=sb;
        k%=p;
	}
    printf("%lld",ans);//cout<<ans;

    return 0;
}

对于读入和输出(getchar()/putchar()>scanf()/printf()>cin/cout(即使有cin,cout快速优化))

像这种比较肮脏的题目 洛谷 也是比较多的大家要注意!!!

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值