zoukankan      html  css  js  c++  java
  • loj #6053 简单的函数 min_25筛

    (color{#0066ff}{ 题目描述 })

    某一天,你发现了一个神奇的函数(f(x)),它满足很多神奇的性质:

    1. (f(1)=1)
    2. (f(p^c)=p oplus c)(p) 为质数,(oplus) 表示异或)。
    3. (f(ab)=f(a)f(b))(a)(b) 互质)。

    你看到这个函数之后十分高兴,于是就想要求出 (sumlimits_{i=1}^n f(i))

    由于这个数比较大,你只需要输出 (sumlimits_{i=1}^n f(i) mod (10^9+7))

    (color{#0066ff}{输入格式})

    一行一个整数 (n)

    (color{#0066ff}{输出格式})

    一行一个整数 (sumlimits_{i=1}^n f(i) mod 1000000007)

    (color{#0066ff}{输入样例})

    6
        
    233333
        
    9876543210
    

    (color{#0066ff}{输出样例})

    16
      
    179004642
      
    895670833
    

    (color{#0066ff}{数据范围与提示})

    对于(30\%)的数据,(n leq 100)

    对于(60\%)的数据,(n leq 10^6)

    对于(100\%)的数据,(1 leq n leq 10^{10})

    (color{#0066ff}{ 题解 })

    min_25筛,我们先找到(f(p))

    不难发现(f(p))=(p oplus 1)

    对于除了2以外的质数(f(p)=p-1,f(2)=3)

    可以把2当成其它来算,最后+2就行了

    还是项(varphi)一样拆项,注意贡献的统计,(f(p^c)=poplus c)

    #include<bits/stdc++.h>
    #define LL  long long
    LL in() {
    	char ch; LL x = 0, f = 1;
    	while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
    	for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
    	return x * f;
    }
    const int maxn = 2e6 + 100;
    const int mod = 1e9+7;
    LL g0[maxn], g1[maxn], a[maxn];
    LL n, m, sqt;
    LL pri[maxn], tot;
    int getid(LL x) { return x <= sqt? x : m - n / x + 1; }
    LL getans(LL a, int b) {
    	if(a < pri[b]) return 0;
    	LL ans = (((g1[getid(a)] - g1[getid(pri[b - 1])]) % mod) - (g0[getid(a)] - g0[getid(pri[b - 1])]) % mod) % mod ;
    	for(int i = b; i <= tot && (LL)pri[i] * pri[i] <= a; i++)
    		for(LL x = pri[i], f = 1; x * pri[i] <= a; x *= pri[i], f++)
    			(ans += (getans(a / x, i + 1) * (pri[i] ^ f) % mod) + (pri[i] ^ (f + 1)) ) %= mod;
    	return ans;
    }
    signed main() {
    	sqt = sqrt(n = in());
    	for(LL i = 1; i <= n; i = a[m] + 1)
    		a[++m] = n / (n / i), g0[m] = ((a[m] % mod) - 1) , g1[m] = (((a[m] % mod) * ((a[m] % mod) + 1)) / 2 - 1) ;
    	for(LL i = 2; i <= sqt; i++) {
    		if(g0[i] != g0[i - 1]) {
    			pri[++tot] = i;
    			LL sqr = i * i;
    			for(int j = m; a[j] >= sqr; j--) {
    				int id = getid(a[j] / i);
    				(g0[j] -= g0[id] - g0[i - 1]) %= mod;
    				(g1[j] -= i * (g1[id] - g1[i - 1]) % mod) %= mod;
    			}
    		}
    	}
    	printf("%lld
    ", ((getans(n, 1) + 1 + (n > 1) * 2)) % mod);
    	return 0;
    }
    
  • 相关阅读:
    CSP2019滚粗记
    [总结] wqs二分学习笔记
    [总结] 圆方树学习笔记
    [CF960G] Bandit Blues
    [总结] 第一类斯特林数
    [EOJ629] 两开花
    [CF286E] Ladies' shop
    [总结] 动态DP学习笔记
    [BZOJ3879] SvT
    [总结] 替罪羊树学习笔记
  • 原文地址:https://www.cnblogs.com/olinr/p/10285821.html
Copyright © 2011-2022 走看看