uoj221【NOI2016】The beauty of cycle

The previous part is relatively simple, it is the brainless formula, let’s talk about it simply.
First of all, this fraction must be considered when \((x,y)=1\) , if pure cycle is required, you might as well guess the conclusion, that is, y must be relatively prime to K. So the answer is \(\sum_{i=1}^n \sum_{j=1}^m [(i,j)=1] [(j,k)=1]\) .

Then use \([(i,j)=1]=\sum_{d|i,j} \mu(d)\) to vigorously unify, and soon you will get:
\[\sum_{d=1} ^{min(n,m)} \mu(d) \frac{n}{d} \sum_{d|j,j\le m}[(j,k)=1]\]
\[=\sum_ {d=1}^{min(n,m)} \mu(d) [(d,k)=1] \frac{n}{d} \sum_{j=1}^{\frac{m} {d}}[(j,k)=1]\]
Let the following lump \(\sum_{j=1}^{\frac{m}{d}}[(j,k)=1]= f(\frac{m}{d})\) , which can be calculated quickly:
\[f(x)=\sum_{j=1}^x [(j,K)=1]\]
\[=\ sum_{j=1}^x \sum_{g|j,k} \mu(g)\]
\[=\sum_{g|k}\mu(g) \sum_{g|j} 1\]
\ [=\sum_{g|k}\mu(g) \frac{x}{g} \]
can be calculated by \(O(\sqrt k)\) .

Back to the original formula
\[\sum_{d=1}^{min(n,m)} \mu(d) [(d,k)=1] \frac{n}{d} f(\frac{m }{d})\]
This can obviously be divided into blocks, preprocess it \(\sum_{d=1}^{min(n,m)} \mu(d)[(d,k)=1]\ ) prefix sum can be \(O(\sqrt n *\sqrt k)\) to calculate the answer, because it is the log of gcd, the preprocessing is not false if it is 2e7.
Then there are 84 points.

Consider quickly finding \(F(k,x)=\sum_{d=1}^x \mu(d)*[(d,k)==1]\) , and also remove the following gcd.
\[F(k,x) =\sum_{d=1}^x \mu(d)*[(d,k)==1] \]
\[ =\sum_{d=1}^x \mu (d) \sum_{g|k,d} \mu(g)\]
\[ =\sum_{g|k} \mu(g) \sum_{g|d} \mu(d)\]
\[ =\sum_{g|k} \mu(g) \sum_{T=1}^{\frac{x}{g}} \mu(T*g)\]
Then because when \((T,g) \ne 1\) \ (\mu(T*g)\) obviously=0.
\[ =\sum_{g|k} \mu(g) \sum_{T=1}^{\frac{x}{g}} [(T,g)==1]*\mu(T)* \mu(g)\]
\[ =\sum_{g|k} \mu^2(g) \sum_{T=1}^{\frac{x}{g}} \mu(T)*[( T,g)==1]\]
\[ =\sum_{g|k} \mu^2(g) F(g,\frac{x}{g})\]
Then recursively calculate, by the way, memorize , in addition, when k=1, it returns directly \(\sum_{i=1}^x \mu(i)\) , so it needs to be preprocessed.

\(F(k,i)\) You can preprocess several items with smaller x when \(k=K\) , which will speed up the speed.

I don’t even know the complexity of Du Jiaosi, I just wrote it after thinking about it, and the limit data ran out and handed it in.Don't ask me what the complexity is, I don't know

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<map>
#define pl puts("lala")
#define cp cerr<<"lala"<<endl
#define fi first
#define se second
#define pb push_back
#define ln putchar('\n')
using namespace std;
inline int read()
{
    char ch=getchar();int g=1,re=0;
    while(ch<'0'||ch>'9') {if(ch=='-')g=-1;ch=getchar();}
    while(ch<='9'&&ch>='0') re=(re<<1)+(re<<3)+(ch^48),ch=getchar();
    return re*g;
}
typedef long long ll;
typedef pair<int,int> pii;

inline int gcd(int a,int b)
{
    while(b) {int t=a%b; a=b; b=t;}
    return a;
}
const int N=7e5+11;
int prime[N],cnt=0,mu[N],smu[N],resf[N],K;
bool isnotprime[N];
void init()
{
    int n=N-11;
    isnotprime[1]=1; mu[1]=1;
    for(int i=2;i<=n;++i) 
    {
        if(!isnotprime[i]) prime[++cnt]=i,mu[i]=-1;
        for(int j=1;j<=cnt&&i*prime[j]<=n;++j)
        {
            isnotprime[i*prime[j]]=1;
            if(!(i%prime[j])) break;
            mu[i*prime[j]]=-mu[i];
        }
    }
    for(int i=1;i<=n;++i) smu[i]=smu[i-1]+mu[i];
    for(int i=1;i<=n;++i) resf[i]=resf[i-1]+mu[i]*(gcd(i,K)==1);
}

map<int,int>mp;
int M(int n)
{
    if(n<=N-11) return smu[n];
    if(mp.count(n)) return mp[n];
    int &ans=mp[n]; ans=1;
    for(int i=2,j;i<=n;i=j+1)
    {
        j=n/(n/i);
        ans-=M(n/i)*(j-i+1);
    }
    return ans;
}

map<int,int>F[2050];
int calcF(int k,int x)
{
    if(k==1) return M(x);
    if(k==K&&x<=N-11) return resf[x];
    if(F[k].count(x)) return F[k][x];
    int &ans=F[k][x];
    for(int i=1;i*i<=k;++i) if(!(k%i))
    {
        if(mu[i]) ans+=mu[i]*mu[i]*calcF(i,x/i);
        if(i*i!=k) 
        {
            int oth=k/i;
            if(mu[oth]) ans+=mu[oth]*mu[oth]*calcF(oth,x/oth);
        }
    }
    return ans;
}

int n,m;
int divi[2050],tot=0;
inline int f(int x)
{
    int ans=0;
    for(int i=1;i<=tot;++i) ans+=mu[divi[i]]*(x/divi[i]);
    return ans;
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);freopen("1.out","w",stdout);
#endif
    n=read(); m=read(); K=read();
    init();
    int mn=min(n,m);
    M(mn);
    for(int i=1;i*i<=K;++i) if(!(K%i))
    {
        divi[++tot]=i;
        if(i*i!=K) divi[++tot]=K/i;
    }
    
    ll ans=0;
    for(int i=1,j;i<=mn;i=j+1)
    {
        j=min(n/(n/i),m/(m/i));
        ans+=1ll*(n/i)*f(m/i)*(calcF(K,j)-calcF(K,i-1));
    }
    cout<<ans<<endl;
    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325209158&siteId=291194637