"NOI2016" beauty cycle of problem-solving report

US "NOI2016" cycle of

For decimal \ (\ FRAC {A} {B} \) , if it is \ (K \) is the binary count, and need to meet the requirements will not be repeated.

We make sure that this does not repeat score is the most simple fraction that is \ ((a, b) = 1 \)

Meet the need to meet the remainder of the first still occurs in the back, the first remainder is \ (A \ BMOD b \) , the back (x \) \ remainder bits actually \ (a \ times k ^ x \ bmod b \)

So we need to meet
\ [a \ equiv a \ times
k ^ x \ pmod b \] solvability

Since \ ((A, B) =. 1 \) , so
\ [k ^ x \ equiv 1
\ pmod b \] If \ ((K, B) =. 1 \) , then the Euler's theorem, solvability \ ( x = \ varphi (x) \ )

Otherwise due \ (k \ times k ^ { x-1} -yb = 1 \) non-integer solution solution, no solution so that the original formula

于是我们需要统计的即为
\[ \sum_{i=1}^m\sum_{j=1}^n[(i,k)=1][(i,j)=1] \]
推式子
\[ \begin{aligned} &\sum_{i=1}^m\sum_{j=1}^n[(i,k)=1][(i,j)=1]\\ =&\sum_{i=1}^m[(i,k)=1]\sum_{j=1}^n\sum_{d=1}^{\min(i,j)}\mu(d)[d|i\land d|j]\\ =&\sum_{d=1}^{\min(n,m)}\mu(d)\lfloor\frac{n}{d}\rfloor\sum_{i=1}^m[(i,k)=1\land d|i]\\ =&\sum_{d=1}^{\min(n,m)}\mu(d)\lfloor\frac{n}{d}\rfloor\sum_{i=1}^{\lfloor\frac{m}{d}\rfloor}[(di,k)=1]\\ =&\sum_{d=1}^{\min(n,m)}\mu(d)[(d,k)=1]\lfloor\frac{n}{d}\rfloor\sum_{i=1}^{\lfloor\frac{m}{d}\rfloor}[(i,k)=1]\\ \end{aligned} \]
我们知道\((a,b)=(a\bmod b,b)\)

Then this question \ (K \) is small, so that we may be pretreated
\ [is (i) = [ (i, k) = 1] \\ f (i) = \ sum_ {j = 1} ^ iis ( J) \]
then the above formula is
\ [\ sum_ {d = 1 } ^ {\ min (n, m)} \ mu (d) is (d \ bmod k) \ lfloor \ frac {n} {d } \ rfloor (\ lfloor \ frac
{m} {dk} \ rfloor f (k) + f (\ lfloor \ frac {m} {d} \ rfloor \ bmod k)) \] so we can \ (O ( k \ log k + n) \ ) in time to solve the problem, you can get \ (84 \) points, good results

Note that we set
\ [F (n) = \
lfloor \ frac {n} {k} \ rfloor f (k) + f (n \ bmod k) \] then the original formula
\ [\ sum_ {d = 1 } ^ {\ min (n, m) } \ mu (d) [(d, k) = 1] \ lfloor \ frac {n} {d} \ rfloor F (\ lfloor \ frac {m} {d} \ rfloor) \]
behind two clearly divisible block, determined considering the front and two prefixes

Set
\ [g (n, k)
= \ sum_ {d = 1} ^ n \ mu (d) [(d, k) = 1] \] Consider the equation push
\ [\ begin {aligned} g ( n, k) = & \ sum_ {d = 1} ^ n \ mu (d) [(d, k) = 1] \\ = & \ sum_ {d = 1} ^ n \ mu (d) \ sum_ { p = 1} ^ {\ min (d, k)} \ mu (p) [p | d \ land p | k] \\ = & \ sum_ {p | k} \ mu (p) \ sum_ {p | d} ^ n \ mu (d ) \\ = & \ sum_ {p | k} \ mu (p) \ sum_ {d = 1} ^ {\ lfloor \ frac {n} {p} \ rfloor} \ mu ( dp) \\ \ mathbb {because \ of} & \ [\ mu (dp) \ not = 0] = [(d, p) = 1], \ mathbb {so} \\ g (n, k) = & \ sum_ {p | k} \ mu (p) \ sum_ {d = 1} ^ {\ lfloor \ frac {n} {p} \ rfloor} \ mu (dp) [(d, p) = 1] \\ = & \ sum_ {p | k } \ mu ^ 2 (p) \ sum_ {d = 1} ^ {\ lfloor \ frac {n} {p} \ rfloor} \ mu (d) [(d, p) = 1] \\ = & \ sum_ {
p | k} \ mu ^ 2 (p) g (\ lfloor \ frac {n} {p} \ rfloor, p) \ end {aligned} \] boundary
\ [g (n , 1) = \ sum_ {d
= 1} ^ n \ mu (d), g (0, k) = 0 \] in front of a screen about to teach du

Complexity really does not forget ...


Code:

#include <cstdio>
#include <cctype>
#include <map>
#include <algorithm>
#define ll long long
using std::min;
const int SIZE=1<<21;
char ibuf[SIZE],*iS,*iT;
//#define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,SIZE,stdin),iS==iT?EOF:*iS++):*iS++)
#define gc() getchar()
template <class T>
void read(T &x)
{
    x=0;char c=gc();
    while(!isdigit(c)) c=gc();
    while(isdigit(c)) x=x*10+c-'0',c=gc();
}
const int N=5e6+1;
int mu[N],pri[N],ispri[N],fmu[N],cnt,toki[2020],aya[2020];
void init()
{
    fmu[1]=mu[1]=1;
    for(int i=2;i<N;i++)
    {
        if(!ispri[i])
        {
            pri[++cnt]=i;
            mu[i]=-1;
        }
        for(int j=1;j<=cnt&&i*pri[j]<N;j++)
        {
            ispri[i*pri[j]]=1;
            if(i%pri[j]) mu[i*pri[j]]=-mu[i];
            else break;
        }
        fmu[i]=fmu[i-1]+mu[i];
    }
}
int gcd(int a,int b){return b?gcd(b,a%b):a;}
std::map <std::pair<int,int>,int> saki;
int g(int x,int k)
{
    //if(x<=1) return n;
    if((k==1&&x<N)||(!x)) return fmu[x];
    std::pair<int,int> now=std::make_pair(x,k);
    if(saki[now]) return saki[now];
    int ret=0;
    if(k==1)
    {
        ret=1;
        for(int l=2,r;l<=x;l=r+1)
        {
            r=x/(x/l);
            ret-=g(x/l,k)*(r+1-l);
        }
    }
    else
    {
        for(int i=1;i*i<=k;i++)
        {
            if(k%i) continue;
            if(mu[i]) ret+=g(x/i,i);
            if(i*i!=k&&mu[k/i]) ret+=g(x/(k/i),k/i);
        }
    }
    return saki[now]=ret;
}
int n,m,k;
int F(int x){return (x/k)*toki[k]+toki[x%k];}
int main()
{
    init();
    read(n),read(m),read(k);
    for(int i=1;i<=k;i++)
        toki[i]=toki[i-1]+(gcd(k,i)==1);
    ll las=0,now,ans=0;
    for(int l=1,r;l<=min(n,m);l=r+1)
    {
        r=min(n/(n/l),m/(m/l));
        ans+=1ll*((now=g(r,k))-las)*(n/l)*F(m/l);
        las=now;
    }
    printf("%lld\n",ans);
    return 0;
}

2019.5.30

Guess you like

Origin www.cnblogs.com/butterflydew/p/10947506.html
Recommended