2018ACM-ICPC徐州网络赛 D Easy Math

mi=1μ(in) 求 解 ∑ i = 1 m μ ( i n )
记: S(m,n)=mi=1μ(in) S ( m , n ) = ∑ i = 1 m μ ( i n )
=μ(n)mi=1μ(i)[gcd(i,n)==1] = μ ( n ) ∑ i = 1 m μ ( i ) [ g c d ( i , n ) == 1 ]
=μ(n)mi=1μ(i)d|i,d|nμ(d) = μ ( n ) ∑ i = 1 m μ ( i ) ∑ d | i , d | n μ ( d )
=μ(n)d|nμ(d)mdi=1μ(id) = μ ( n ) ∑ d | n μ ( d ) ∑ i = 1 ⌊ m d ⌋ μ ( i d )
=μ(n)d|nμ(d)S(md,d) = μ ( n ) ∑ d | n μ ( d ) S ( ⌊ m d ⌋ , d )
直接递归做吧
n=1 n = 1 时,返回 mi=1μ(i) ∑ i = 1 m μ ( i ) ,这个可以参考我的另一篇https://blog.csdn.net/meopass/article/details/82628563。

#define others
#ifdef poj
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#endif // poj
#ifdef others
#include 
#include 
#include 
#endif // others
//#define file
#define all(x) x.begin(), x.end()
using namespace std;
using namespace __gnu_pbds;
using namespace __gnu_cxx;
#define eps 1e-8
const double pi = acos(-1.0);

typedef long long LL;
typedef long long DLL;
typedef unsigned long long ULL;
void umax(LL &a, LL b) {
    a = max(a, b);
}
void umin(LL &a, LL b) {
    a = min(a, b);
}
int dcmp(double x) {
    return fabs(x) <= eps?0:(x > 0?1:-1);
}
void file() {
    freopen("data_in.txt", "r", stdin);
    freopen("data_out.txt", "w", stdout);
}

DLL mod = 1e9+7;

DLL Pow(DLL a,DLL b) {
    DLL res=1;
    a%=mod;
    for(; b; b>>=1) {
        if(b&1)res=res*a%mod;
        a=a*a%mod;
    }
    return res;
}
//
//void print(DLL x) {
//    if(x < 0) {
//        x = -x;
//        putchar('-');
//    }
//    if(x > 9) print(x/10);
//    putchar(x%10 + '0');
//}
//#define iostart

#define pb(x) push_back(x)
namespace solver {
    const LL maxn = 1e7;
    map, LL> mp;
    bool tag[maxn];
    LL p[maxn/10], mob[maxn], premob[maxn];
    LL cnt;
    void shai() {
        mob[1] = 1;
        cnt = 0;
        for (LL i = 2; i < maxn; i++) {
            if (!tag[i]) {
                p[cnt++] = i;
                mob[i] = -1;
            }
            for (LL j = 0; j < cnt && i * p[j] < maxn; j++) {
                tag[i*p[j]] = 1;
                if (i % p[j] == 0){
                    mob[i*p[j]]=0;
                    break;
                }
                mob[i*p[j]] = -mob[i];
            }
        }
        for (LL i = 1; i < maxn; i++) {
            premob[i] = premob[i-1] + mob[i];
        }
    }
    LL getmu(LL n) {
        if (n < maxn) return mob[n];
        LL ans = 1;
        for (int i = 2; i <= sqrt(n); i++) {
            if (n % i == 0) {
                int cnt = 0;
                while (n % i == 0) {
                    n /= i;
                    cnt ++;
                    if (cnt >= 2) return 0;
                }
                ans *= -1;
            }
        }
        if (n != 1) {
            ans *= -1;
        }
        return ans;
    }
    unordered_map mppremu;
    LL getpremu(LL n) {
        if (n < maxn) {
            return premob[n];
        }
        if (mppremu.count(n)) {
            return mppremu[n];
        }
        LL ans = 1;
        for (LL i = 2, last; i <= n; i=last+1) {
            last = n / (n / i);
            ans -= (last - i + 1) * getpremu(n/i);
        }
        return mppremu[n] = ans;
    }
    LL get(LL m, LL n) {
        if (m == 0) {
            return 0;
        }
        if (n == 1) {
            return getpremu(m);
        }
        LL v = getmu(n);
        if (m == 1) {
            return v;
        }
        if (v == 0) {
            return 0;
        }
        if (mp.count({m, n})) return mp[{m, n}];
        LL ans = 0;
        for (LL i = 1; i <= sqrt(n); i++) {
            if (n % i == 0) {
                ans += get(m/i, i)*getmu(i);
                if (i * i != n) {
                    ans += get(m/(n/i), n/i)*getmu(n/i);
                }
            }
        }
        return mp[{m,n}] = v * ans;
    }
    void solve() {
        shai();
        LL m, n;
        scanf("%lld%lld", &m, &n);
        printf("%lld\n", get(m, n));
    }
}

int main() {
#ifdef iostart
    ios::sync_with_stdio(0);
    cin.tie(0);
#endif // iostart
//    file();
    solver::solve();
    return 0;
}

你可能感兴趣的:(数学,杜教筛)