zoukankan      html  css  js  c++  java
  • BZOJ3561 DZY Loves Math VI 【莫比乌斯反演】

    题目

    给定正整数n,m。求

    输入格式

    一行两个整数n,m。

    输出格式

    一个整数,为答案模1000000007后的值。

    输入样例

    5 4

    输出样例

    424

    提示

    数据规模:

    1<=n,m<=500000,共有3组数据。

    题解

    套路反演:

    [egin{aligned} ans &= sumlimits_{d = 1}^{n} sumlimits_{i = 1}^{lfloor frac{n}{d} floor} sumlimits_{j = 1}^{lfloor frac{m}{d} floor} (frac{id * jd}{d})^{d} qquad [gcd(i,j) == 1] \ &= sumlimits_{d = 1}^{n} d^{d} sumlimits_{i = 1}^{lfloor frac{n}{d} floor} sumlimits_{j = 1}^{lfloor frac{m}{d} floor} i^{d}j^{d} qquad [gcd(i,j) == 1] \ &= sumlimits_{d= 1}^{n} d^{d} sumlimits_{k = 1}^{lfloor frac{n}{d} floor} mu(k) k^{2d} sumlimits_{i = 1}^{lfloor frac{n}{kd} floor} i^{d} sumlimits_{j = 1}^{lfloor frac{m}{kd} floor} j^{d} end{aligned} ]

    然后就慌了,好像搞不下去了
    仔细分析一下复杂度,对于每个(d),里面那堆玩意只需要(O(lfloor frac{m}{d} floor))就可以计算出来
    所以复杂度为(n)乘一个调和级数
    (O(nlogn))

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #define LL long long int
    #define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
    #define REP(i,n) for (int i = 1; i <= (n); i++)
    #define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<' '; puts("");
    using namespace std;
    const int maxn = 500005,maxm = 100005,INF = 1000000000,P = 1e9 + 7;
    int p[maxn],isn[maxn],pi,mu[maxn],n,m;
    LL a[maxn],sum[maxn];
    LL qpow(LL a,LL b){
    	LL ans = 1;
    	for (; b; b >>= 1, a = a * a % P)
    		if (b & 1) ans = ans * a % P;
    	return ans;
    }
    void init(){
    	mu[1] = 1;
    	for (int i = 2; i <= n; i++){
    		if (!isn[i]) p[++pi] = i,mu[i] = -1;
    		for (int j = 1; j <= pi && i * p[j] <= n; j++){
    			isn[i * p[j]] = true;
    			if (i % p[j] == 0){
    				mu[i * p[j]] = 0;
    				break;
    			}
    			mu[i * p[j]] = -mu[i];
    		}
    	}
    }
    int main(){
    	scanf("%d%d",&n,&m);
    	if (n > m) swap(n,m);
    	init();
    	REP(i,m) a[i] = 1;
    	LL ans = 0;
    	for (int d = 1; d <= n; d++){
    		for (LL i = 1; i <= m / d; i++){
    			a[i] = a[i] * i % P;
    			sum[i] = (sum[i - 1] + a[i]) % P;
    		}
    		LL tmp = 0;
    		for (int k = 1; k <= n / d; k++){
    			tmp = (tmp + (mu[k] * qpow(k,2 * d) % P + P) % P * sum[n / (k * d)] % P * sum[m / (k * d)] % P);
    			tmp = (tmp + P) % P;
    		}
    		ans = (ans + qpow(d,d) * tmp % P) % P;
    	}
    	ans = (ans % P + P) % P;
    	printf("%lld
    ",ans);
    	return 0;
    }
    
    
  • 相关阅读:
    Leetcode Substring with Concatenation of All Words
    Leetcode Divide Two Integers
    Leetcode Edit Distance
    Leetcode Longest Palindromic Substring
    Leetcode Longest Substring Without Repeating Characters
    Leetcode 4Sum
    Leetcode 3Sum Closest
    Leetcode 3Sum
    Leetcode Candy
    Leetcode jump Game II
  • 原文地址:https://www.cnblogs.com/Mychael/p/8976442.html
Copyright © 2011-2022 走看看