zoukankan      html  css  js  c++  java
  • [NOI 2016]循环之美

    Description

    题库链接

    给出十进制下的 (n,m,k) ,求 (frac{i}{j},iin[1,n],jin[1,m])(k) 进制下不同的纯循环小数个数。

    纯循环小数定义为该数小数点后全部都是循环节。

    (1leq n,mleq 10^9,1leq kleq 2000)

    Solution

    首先考虑怎样的 (frac{x}{y}) 会满足“纯循环”小数。

    比较显然的是(题目中给出了提示)只要 (exists ainmathbb{N^*})

    [egin{aligned}x&equiv xcdot k^a&pmod{y}\1&equiv k^a&pmod{y}end{aligned}]

    (gcd(k^a,y)=1Rightarrow gcd(k,y)=1)

    那么现在式子就变成求

    [sum_{i=1}^nsum_{j=1}^m[gcd(i,j)=1][gcd(j,k)=1]]

    我们先把奇奇怪怪的东西丢一边,依照套路

    [egin{aligned}Rightarrow &sum_{i=1}^nsum_{j=1}^msum_{dmid gcd(i,j)}mu(d)[gcd(j,k)=1]\=&sum_{d=1}^{min{n,m}}mu(d)leftlfloorfrac{n}{d} ight floorsum_{j=1}^{leftlfloorfrac{m}{d} ight floor}[gcd(jd,k)=1]end{aligned}]

    由于 (gcd(jd,k)=1Leftrightarrow gcd(j,k)=1wedgegcd(d,k)=1) ,那么

    [Rightarrow sum_{d=1}^{min{n,m}}[gcd(d,k)=1]mu(d)leftlfloorfrac{n}{d} ight floorsum_{j=1}^{leftlfloorfrac{m}{d} ight floor}[gcd(j,k)=1]]

    不妨记 (sumlimits_{j=1}^{leftlfloorfrac{m}{d} ight floor}[gcd(j,k)=1]=Fleft(leftlfloorfrac{m}{d} ight floor ight)) ,注意到 (gcd(j,k)=gcd(j-k,k)) ,那么这个 (F) 很好求

    [F(n)=leftlfloorfrac{n}{k} ight floor f(k)+f(nmod{k})]

    其中 (f(n)) 表示 (sumlimits_{j=1}^{min{n,k}}[gcd(j,k)=1]) 。这个可以 (O(klog(k))) 预处理出来。 (O(1)) 回答询问。

    那么原式变成

    [sum_{d=1}^{min{n,m}}leftlfloorfrac{n}{d} ight floor Fleft(leftlfloorfrac{m}{d} ight floor ight)[gcd(d,k)=1]mu(d)]

    ([gcd(d,k)=1]mu(d)=g(d)) ,考虑如何求 (g(d))

    这里比较巧妙,我们假设 (M(n)=sumlimits_{i=1}^n mu(i)) 。可以得到

    [egin{aligned}g(n)&=M(n)-sum_{i=2}^{min{k,n}}[imid k]sum_{j=1}^{leftlfloorfrac{n}{d} ight floor}[gcd(j,k)=1]mu(ji)\&=M(n)-sum_{i=2}^{min{k,n}}[imid k]mu(i)sum_{j=1}^{leftlfloorfrac{n}{d} ight floor}[gcd(j,k)=1]mu(j)\&=M(n)-sum_{i=2}^{min{k,n}}[imid k]mu(i)g(leftlfloorfrac{n}{d} ight floor)end{aligned}]

    那么可以枚举 (k) 的因数类似于杜教筛来求解。

    复杂度为 (Oleft(n^{frac{2}{3}}+sigma_0(k)sqrt{n} ight))

    Code

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int N = 233333+5;
    
    int n, m, k, mu[N], prime[N], isprime[N], tot;
    map<int, ll>mmu, mg; ll ans;
    int f[N], sum[N], g[N], factor[N], cnt;
    
    int gcd(int a, int b) {return b ? gcd(b, a%b) : a; }
    void get() {
        memset(isprime, 1, sizeof(isprime));
        isprime[1] = 0; mu[1] = g[1] = sum[1] = 1;
        for (int i = 2; i < N; i++) {
            if (isprime[i]) mu[prime[++tot] = i] = -1;
            for (int j = 1; j <= tot && i*prime[j] < N; j++) {
                if (i%prime[j]) mu[i*prime[j]] = -mu[i];
                isprime[i*prime[j]] = 0;
                if (i%prime[j] == 0) break;
            }
            sum[i] = sum[i-1]+mu[i]; g[i] = g[i-1];
            if (gcd(i, k) == 1) g[i] += mu[i];
        }
        for (int i = 1; i <= k; i++) {
            f[i] = f[i-1]; if (gcd(i, k) == 1) ++f[i];
            if (k%i == 0 && i != 1) factor[++cnt] = i;
        }
    }
    
    ll gmu(int x) {
        if (x < N) return sum[x];
        if (mmu.count(x)) return mmu[x];
        ll ans = 1;
        for (int last, i = 2; i <= x; i = last+1) {
            last = x/(x/i);
            ans -= 1ll*(last-i+1)*gmu(x/i);
        }
        return mmu[x] = ans;
    }
    ll gg(int x) {
        if (x < N) return g[x];
        if (mg.count(x)) return mg[x];
        ll ans = gmu(x);
        for (int i = 1; i <= cnt && factor[i] <= x; i++)
            ans -= 1ll*mu[factor[i]]*gg(x/factor[i]);
        return mg[x] = ans; 
    }
    ll F(int x) {return 1ll*x/k*f[k]+f[x%k]; }
    void work() {
        scanf("%d%d%d", &n, &m, &k); get();
        for (int last, i = 1; i <= min(n, m); i = last+1) {
            last = min(n/(n/i), m/(m/i));
            ans += 1ll*F(m/i)*(n/i)*(gg(last)-gg(i-1));
        }
        printf("%lld
    ", ans);
    }
    int main() {work(); return 0; }
  • 相关阅读:
    requests
    urllib
    爬虫初入
    Django之admin
    Django之FileField字段
    边学边练之博客园----登录验证
    边学边练之博客园----设计表
    Django之中间件
    计算机基础
    win—命令行窗口一层一层的打开文件
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/9259545.html
Copyright © 2011-2022 走看看