• hdu5608 function


    Description

    There is a function f(x),which is defined on the natural numbers set N,satisfies the following eqaution
    
    N2−3N+2=∑d|Nf(d)
    
    calulate ∑Ni=1f(i)  mod 109+7
    

    Input

    the first line contains a positive integer T,means the number of the test cases.
    
    next T lines there is a number N
    
    
    T≤500,N≤109
    

    only 5 test cases has N>106
    .

    Output

    Tlines,each line contains a number,means the answer to the i
    -th test case.
    

    Sample Input

    1
    3
    

    Sample Output

    2
    
    $1^2-3*1+2=f(1)=0$
    $2^2-3*2+2=f(2)+f(1)=0->f(2)=0$
    $3^2-3*3+2=f(3)+f(1)=2->f(3)=2$
    $f(1)+f(2)+f(3)=2$
    

    Solution

    两种方法:杜教筛,杜教筛+莫比乌斯反演

    1.杜教筛+莫比乌斯反演

    这貌似是我第一次真正意义上用莫比乌斯反演公式。。。
    (F(n)=sum_{d|n}f(d)=n^2-3n+2)
    则有(f(n)=sum_{d|n}mu(d)F(frac{n}{d}))

    [egin{aligned} &sum_{i=1}^{n}f(i)\ &=sum_{i=1}^{n}sum_{d|i}mu(d)F(frac{n}{d})\ &=sum_{d=1}^nmu(d)sum_{i=1}^{lfloorfrac{n}{d} floor}F(i) end{aligned} ]

    前面那个(mu(d))杜教筛,后面那个推一下可以(O(1))
    (sum_{i=1}^n{i^2-3i+2}=frac{n(n-1)(n-2)}{3})

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdlib>
    #include <cstdio>
    #include <vector>
    #include <queue>
    #include <cmath>
    #include <stack>
    #include <deque>
    #include <map>
    #include <set>
    
    #define ll long long
    #define inf 0x3f3f3f3f
    #define il inline
    
    namespace io {
    
    #define in(a) a = read()
    #define out(a) write(a)
    #define outn(a) out(a), putchar('
    ')
    
    #define I_int ll
    inline I_int read() {
        I_int x = 0, f = 1;
        char c = getchar();
        while (c < '0' || c > '9') {
            if (c == '-') f = -1;
            c = getchar();
        }
        while (c >= '0' && c <= '9') {
            x = x * 10 + c - '0';
            c = getchar();
        }
        return x * f;
    }
    char F[200];
    inline void write(I_int x) {
        if (x == 0) return (void) (putchar('0'));
        I_int tmp = x > 0 ? x : -x;
        if (x < 0) putchar('-');
        int cnt = 0;
        while (tmp > 0) {
            F[cnt++] = tmp % 10 + '0';
            tmp /= 10;
        }
        while (cnt > 0) putchar(F[--cnt]);
    }
    #undef I_int
    
    }
    using namespace io;
    
    using namespace std;
    
    const int N = 5e6;
    const ll mod = 1e9 + 7;
    
    ll n, m;
    bool vis[N+10];
    int p[N/10], cnt;
    int mu[N], s[30000];
    
    void init(int n) {
    	mu[1] = 1;
    	for(int i = 2; i <= n; ++i) {
    		if(!vis[i]) p[++cnt] = i, mu[i] = -1;
    		for(int j = 1; j <= cnt && i * p[j] <= n; ++j) {
    			vis[i * p[j]] = 1;
    			if(i % p[j] == 0) break;
    			mu[i * p[j]] = -mu[i];
    		}
    	}
    	for(int i = 1; i <= n; ++i) mu[i] += mu[i - 1];
    }
    
    int S(ll n) {
    	if(n <= N) return mu[n];
    	if(vis[m / n]) return s[m / n];
    	vis[m / n] = 1;
    	int ans = 1;
    	for(ll l = 2, r; l <= n; l = r + 1) {
    		r = n / (n / l);
    		ans -= (r - l + 1) * S(n / l);
    		ans %= mod; ans += mod; ans %= mod;
    	}
    	return s[m / n] = ans;
    }
    
    ll power(ll a, ll b) { ll ans = 1;
    	while(b) {
    		if(b & 1) ans = ans * a % mod;
    		a = a * a % mod; b >>= 1;
    	} 
    	return ans;
    }
    
    ll inv3 = power(3, mod - 2);
    ll calc(ll n) {
    	return n * (n - 1) % mod * (n - 2) % mod * inv3 % mod;
    }
    
    int main() {
    	init(N);
    	int T = read();
    	while(T--) {
    		n = read();
    		memset(vis, 0, sizeof(vis));
    		m = n;
    		ll ans = 0;
    		for(ll l = 1, r; l <= n; l = r + 1) {
    			r = n / (n / l);
    			ans += 1ll * (S(r) - S(l - 1) + mod) % mod * calc(n / l) % mod ;
    			ans %= mod;
    		}
    		printf("%lld
    ", ans);
    	}
    }
    

    2.杜教筛

    现在才知道杜教筛可以筛普通数论函数,不一定要积性函数。
    那么就很简单了,套路的给(f)卷上(1),则有(f*1=g=n^2-3n+2)
    至于预处理g的前缀和,这玩意不是积性函数不能线性筛。但是可以(nlogn)暴力筛出来。方法很多,因为我是写了方法1再来写方法2的所以我直接又反演了一下来筛。。。

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdlib>
    #include <cstdio>
    #include <vector>
    #include <queue>
    #include <cmath>
    #include <stack>
    #include <deque>
    #include <map>
    #include <set>
    
    #define ll long long
    #define inf 0x3f3f3f3f
    #define il inline
    
    namespace io {
    
    #define in(a) a = read()
    #define out(a) write(a)
    #define outn(a) out(a), putchar('
    ')
    
    #define I_int ll
    inline I_int read() {
        I_int x = 0, f = 1;
        char c = getchar();
        while (c < '0' || c > '9') {
            if (c == '-') f = -1;
            c = getchar();
        }
        while (c >= '0' && c <= '9') {
            x = x * 10 + c - '0';
            c = getchar();
        }
        return x * f;
    }
    char FF[200];
    inline void write(I_int x) {
        if (x == 0) return (void) (putchar('0'));
        I_int tmp = x > 0 ? x : -x;
        if (x < 0) putchar('-');
        int cnt = 0;
        while (tmp > 0) {
            FF[cnt++] = tmp % 10 + '0';
            tmp /= 10;
        }
        while (cnt > 0) putchar(FF[--cnt]);
    }
    #undef I_int
    
    }
    using namespace io;
    
    using namespace std;
    
    const int N = 1e6;
    const ll mod = 1e9 + 7;
    
    ll n, m;
    bool vis[N+10];
    int p[N/10], cnt;
    ll s[N], F[N];
    
    ll power(ll a, ll b) { ll ans = 1;
    	while(b) {
    		if(b & 1) ans = ans * a % mod;
    		a = a * a % mod; b >>= 1;
    	} 
    	return ans;
    }
    
    ll inv3 = power(3, mod - 2);
    ll calc(ll n) {
    	n %= mod;
    	return n * (n - 1) % mod * (n - 2) % mod * inv3 % mod;
    }
    
    int mu[N];
    void init(int n) {
    	mu[1] = 1;
    	for(int i = 2; i <= n; ++i) {
    		if(!vis[i]) p[++cnt] = i, mu[i] = -1;
    		for(int j = 1; j <= cnt && i * p[j] <= n; ++j) {
    			vis[i * p[j]] = 1;
    			if(i % p[j] == 0) break;
    			mu[i * p[j]] = -mu[i];
    		}
    	}
    	for(int i = 1; i <= n; ++i) {
    		ll g = (ll)(((ll)i * i % mod - 3ll * i % mod + 2ll) % mod + mod) % mod;
    		for(int j = i; j <= n; j += i) {
    			F[j] += 1ll * mu[j / i] * g % mod;
    			F[j] %= mod;
    		}
    	}
    	for(int i = 1; i <= n; ++i) F[i] += F[i - 1], F[i] %= mod;
    }
    
    ll S(ll n) {
    	if(n <= N) return F[n];
    	if(vis[m / n]) return s[m / n];
    	vis[m / n] = 1;
    	ll ans = calc(n);
    	for(ll l = 2, r; l <= n; l = r + 1) {
    		r = n / (n / l);
    		ans -= (r - l + 1) * S(n / l) % mod;
    		ans %= mod; ans += mod; ans %= mod;
    	}
    	return s[m / n] = (ans % mod + mod) % mod;
    }
    
    int main() {
    	init(N);
    	int T = read();
    	while(T--) {
    		n = read();
    		memset(vis, 0, sizeof(vis));
    		m = n;
    		printf("%lld
    ", (S(n) + mod) % mod);
    	}
    }
    
  • 相关阅读:
    高斯函数 and 对数高斯函数 拟合曲线
    Python3.6、3.7、3.8新特性
    常用限流策略——漏桶与令牌桶介绍
    常用的HTTP服务压测工具介绍
    使用swagger生成接口文档
    validator库参数校验若干实用技巧
    树形结构数据处理
    element-ui 抽屉组件(el-drawer ) 二次封装 增加resize拖曳改变宽度大小
    pm2常用命令
    vue3-- setup中获取数组dom
  • 原文地址:https://www.cnblogs.com/henry-1202/p/10363375.html
Copyright © 2020-2023  润新知