zoukankan      html  css  js  c++  java
  • 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);
    	}
    }
    
  • 相关阅读:
    SD卡测试
    测试人员可能会遇到的问题
    HDU 1024 Max Sum Plus Plus
    HDU 1176 免费馅饼
    HDU 1257 最少拦截系统
    HDU 1087 Super Jumping! Jumping! Jumping!
    poj 1328 Radar Installation
    poj 1753 Flip Game
    HDU 1003 Max Sum
    HDU 5592 ZYB's Premutation(BestCoder Round #65 C)
  • 原文地址:https://www.cnblogs.com/henry-1202/p/10363375.html
Copyright © 2011-2022 走看看