zoukankan      html  css  js  c++  java
  • BZOJ 3309: DZY Loves Math (莫比乌斯反演)

    反演比较简单,可以化成Ans=k=1min(n,m)nkmkdkμ(kd)f(d)large Ans=sum_{k=1}^{min(n,m)}lfloor{frac{n}{k}} floorlfloor{frac{m}{k}} floorsum_{d|k}mu(frac kd)f(d)

    后面这一坨怎么推的具体见 FromATP的博客

    不看题解我不会aaa…w(゚Д゚)w

    CODE

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int MAXN = 10000000;
    int prime[MAXN/10], cnt, e[MAXN+5], g[MAXN+5];
    LL F[MAXN+5];
    bool vis[MAXN+5];
    inline void Pre_Work(int n) {
    	F[1] = e[1] = 0; g[1] = 1;
    	for(int i = 2; i <= n; ++i) {
    		if(!vis[i])
    			prime[++cnt] = i, F[i] = e[i] = 1, g[i] = i;
    		for(int j = 1; j <= cnt && i*prime[j] <= n; ++j) {
    			vis[i*prime[j]] = 1;
    			if(i % prime[j] == 0) {
    				g[i*prime[j]] = g[i] * prime[j];
    				e[i*prime[j]] = e[i] + 1;
    				int tmp = i / g[i];
    				if(tmp == 1) F[i*prime[j]] = 1;
    				else F[i*prime[j]] = (e[i*prime[j]] == e[tmp] ? -F[tmp] : 0);
    				break;
    			}
    			g[i*prime[j]] = prime[j];
    			e[i*prime[j]] = 1;
    			F[i*prime[j]] = (e[i] == 1 ? -F[i] : 0);
    		}
    	}
    	for(int i = 2; i <= n; ++i) F[i] += F[i-1];
    }
    
    inline LL solve(int n, int m) {
    	if(m < n) swap(n, m);
    	LL re = 0;
    	for(int i = 1, j; i <= n; i = j+1) {
    		j = min(n/(n/i), m/(m/i));
    		re += 1ll * (n/i) * (m/i) * (F[j] - F[i-1]);
    	}
    	return re;
    }
    int main() {
    	int n, m, T;
    	scanf("%d", &T);
    	Pre_Work(MAXN);
    	while(T--) {
    		scanf("%d%d", &n, &m);
    		printf("%lld
    ", solve(n, m));
    	}
    }
    
  • 相关阅读:
    数论 欧几里德算法 以及 欧几里得拓展
    数论 快速幂的原理讲解
    汉诺塔模板
    C++ 迭代器运算
    C++ STL vector set map 简易用法
    C++ 使用指向函数的指针数组
    Codeforces 718C 线段树+矩乘
    BZOJ 2506 分块
    Codeforces 455D 分块+链表
    Codeforces 19E 树上差分
  • 原文地址:https://www.cnblogs.com/Orz-IE/p/12039291.html
Copyright © 2011-2022 走看看