• 欢迎光临~

8.24

开发技术 开发技术 2022-08-25 次浏览

ABC212G

题意:

给定数字(P)

求有多少对((x,y)),满足(0leq x,y<P),而且存在正整数(n),满足(x^nequiv y (mod P))

(Pleq 10^{12})(P)是质数

(r)(P)的原根

那么(x,y)可以表示为(x=r^a,y=r^b)

原式为(r^{an}=r^b (mod P))

把指数拿下来

(an=b (mod P-1))

(n=P-1)

于是答案是((sum_{i=1}^{n}frac{n}{gcd(n,i)})+1)

加一是因为有((0,0))

按照套路,把枚举(i)变成枚举(g=gcd(n,i))

(sum_{g|n}frac{n}{g}*f(g))

其中(f(g)=sum_{i=1}^n[gcd(n,i)==g])

因为(n)的因数不多,假设数量为(m),容斥求(f(g))的复杂度是(O(m^2))

所以复杂度就是(O(sqrt{n}+m^2))

#include<bits/stdc++.h>
using namespace std;
namespace red{
#define int long long
#define double long double
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define lowbit(i) ((i)&(-i))
#define mid ((l+r)>>1)
#define eps (1e-15)
    const int N=1e6+10,mod=998244353,inv2=5e8+4,inf=2e15;
    void __init(int n=2000) {}
    
    inline void main()
    {
        int n;
        cin>>n;
        --n;
        int ans=1;
        vector<int> d;
        for(int i=1;i*i<=n;++i)
        {
            if(n%i==0)
            {
                d.emplace_back(i);
                if(i*i!=n) d.emplace_back(n/i);
            }
        }
        sort(d.begin(),d.end());
        int m=d.size();
        vector<int> f(m);
        for(int i=m-1;i>=0;--i)
        {
            f[i]=n/d[i];
            for(int j=i+1;j<m;++j)
            {
                if(d[j]%d[i]==0) f[i]-=f[j];
            }
        }
        for(int i=0;i<m;++i) ans=(ans+((n/d[i])%mod*(f[i]%mod))%mod)%mod;
        cout<<ans<<'n';
    }
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    red::__init();
    int qwq=1; //cin>>qwq;
    while(qwq--) red::main();
    return 0;
}
/*

*/

程序员灯塔
转载请注明原文链接:8.24
喜欢 (0)