• 「$mathcal{Darkbzoj}$」神犇和蒟蒻


    题目描述

    很久很久以前,有一只神犇叫 (yzy)

    很久很久之后,有一只蒟蒻叫 (lty)

    输入格式

    请你读入一个整数 (N,1leq Nleq 10^9)

    输出格式

    请你输出一个整数 (A,B),模 (10^9+7)

    [egin{aligned} A&=sum_{i=1}^N{mu (i^2)}\ B&=sum_{i=1}^N{varphi (i^2)} end{aligned} ]

    输入输出样例

    输入

    1
    

    输出

    1
    1
    

    题解

    首先根据 (mu) 函数的性质,容易得到,第一个式子中,只有 (i=1) 时才会对答案贡献 (1),其他项都是 (0),所有第一个答案永远是 (1)

    然后考虑如何求 (B),首先根据 (varphi) 函数的性质可以得到

    [varphi(ij)=frac{varphi(i)varphi(j)gcd(i,j)}{varphi(gcd(i,j))} ]

    那么原式子可以转化为

    [sum_{i=1}^N{varphi (i)i} ]

    这个可以套用杜教筛去做,具体证明见杜教筛

    代码
    #include <cstdio>
    #include <unordered_map>
    
    typedef long long ll;
    
    using namespace std;
    
    const int mod = 1e9 + 7, inv = 166666668;
    
    inline int addmod (register int a, register int b) {
    	return a += b, a >= mod ? a - mod : a;
    }
    
    inline int delmod (register int a, register int b) {
    	return a -= b, a < 0 ? a + mod : a;
    }
    
    inline ll mulmod (register ll a, register int b) {
    	return a *= b, a >= mod ? a % mod : a;
    }
    
    int n, cnt;
    int prime[3000005], phi[3000005], sum[3000005];
    bool vis[3000005];
    unordered_map <int, int> f;
    
    inline void xxs () {
    	phi[1] = sum[1] = 1;
    	for (register int i = 2; i <= 3e6; i ++) {
    		if (! vis[i]) prime[++ cnt] = i, phi[i] = i - 1;
    		for (register int j = 1; j <= cnt && i * prime[j] <= 3e6; j ++) {
    			vis[i * prime[j]] = 1;
    			if (i % prime[j] == 0) {
    				phi[i * prime[j]] = phi[i] * prime[j];
    				break;
    			}
    			phi[i * prime[j]] = phi[i] * phi[prime[j]];
    		}
    		sum[i] = addmod (sum[i - 1], mulmod (phi[i], i));
    	}	
    }
    
    inline int Getsum (register int l, register int r) {
    	return 1ll * (l + r) * (r - l + 1) / 2 % mod;
    }
    
    inline int Getsum2 (register int n) {
    	return mulmod (mulmod (mulmod (n, n + 1), 2 * n + 1), inv);
    }
    
    inline int F (register int n) {
    	if (n <= 3e6) return sum[n];
    	if (f[n]) return f[n];
    	register int ans = Getsum2 (n);
    	for (register int l = 2, r; l <= n; l = r + 1)
    		r = n / (n / l), ans = delmod (ans, mulmod (Getsum (l, r), F (n / l)));
    	return f[n] = ans;
    }
    
    int main () {
    	scanf ("%d", &n), xxs (), printf ("1
    %d
    ", F (n));
    	return 0;
    }
    
  • 相关阅读:
    Java中如何判断一个字符串是否为数字
    Web发展简史
    常用编程语言
    浏览器运行原理
    [LeetCode]69. x 的平方根(数学,二分)
    [计算机网络]TCP/IP协议-运输层
    [剑指Offer]33-根据后序序列判断是否能组成BST
    [剑指Offer]17-打印从1到最大的n位数(递归)
    [剑指Offer]56-数组中数字出现的次数(位运算)
    [剑指Offer]18-题目一:删除链表的节点 题目二:删除链表中重复节点
  • 原文地址:https://www.cnblogs.com/Rubyonly233/p/14955986.html
Copyright © 2020-2023  润新知