• 2020.1.17 小测


    总结 link

    已知 (f(x) = displaystyle sum_{d|x}μ(d)∗d)

    现在请求出下面式子的值

    (displaystyle sum_{i=1}^n sum_{j=1}^nf(gcd(i,j))∗f(lcm(i,j)))

    由于值可能过大所以请对 10^9+7 取模

    (n≤10^9)

    输入

    一行一个整数 n
    

    输出

    一行一个数字,为问题描述所求的值
    

    输入样例

    4
    

    输出样例

    9
    

    正解

    看到 gcd 与 lcm 就想乘起来 , 得到 i * j , 考试时我也这么做了 , 结果也没写出来 。

    考完之后听老师讲 , 才发现 f 不是完全积性函数 , 而 gcd 与 lcm 也不互质 , 心里一阵发慌。。。。。。

    不过吧 , 正解就是 (f(gcd(i , j)) * f(lcm(i , j)) = f(i) * f(j)) 原因吧。。

    把 i , j 质因数分解, 没有的就当成 0 次幂 。

    gcd 就相当于 , 两者的指数取min , lcm 就相当于取 max , 设 两个指数分别是 c1 , c2;

    (p^{c1} * p^{c2} = p^{max(c1 , c2) + min(c1 , c2)}) 瞎猫碰见了死耗子。。。。。。

    这样就是 (ans = displaystyle {sum_{i=1}^nf(i)}^2)

    [large{ egin{aligned} ans =& sum_{i=1}^nsum_{j|i}j * mu(j) \ =&sum_{d=1}^nsum_{i=1}^{n/d}d * mu(d)\ =&sum_{d=1}^nd * mu(d) * (n/d) \ end{aligned} } ]

    (n / d) 可以整除分块 , 之后就是计算(d * mu(d)) 的前缀和

    (g(x) = x * mu(x))

    [large{ egin{aligned} (g * id)(x) &= sum_{d|x}d * mu(d) * (n/d) \ &= sum_{d|x}mu(d) \ &= e end{aligned} } ]

    很神奇吧 , 之后就是杜教筛的板子了 , 放代码

    #include<iostream>
    #include<cstdio>
    #include<map>
    using namespace std;
    const int mod = 1e9+7 , N = 2e6 + 100 , maxn = 2e6;
    #define int long long
    int n , tot;
    map<int,int> w;
    int prime[N] , vis[N] , mu[N] , f[N];
    void Init(int maxn)
    {
    	mu[1] = 1;
    	for(int i = 2 ; i <= maxn ; ++i)
    	{
    		if(!vis[i]) prime[++tot] = i , mu[i] = -1;
    		for(int j = 1 ; j <= tot && i * prime[j] <= maxn ; ++j)
    		{
    			vis[i * prime[j]] = 1;
    			if(i % prime[j] == 0)
    			{
    				mu[i * prime[j]] = 0;
    				break;
    			}
    			mu[i * prime[j]] = -mu[i];
    		}
    	}
    	for(int i = 1 ; i <= maxn ; ++i) f[i] = (f[i-1] + mu[i] * i % mod) % mod;
    	return ;
    }
    
    int get(int n)
    {
    	if(n <= maxn) return f[n];
    	if(w.count(n)) return w[n];
    	int res = 0;
    	for(int i = 2 , r ; i <= n ; i = r + 1)
    	{
    		r = min(n , n / (n / i));
    		res = (res + get(n / i) * ((i + r) * (r - i + 1) / 2) % mod) % mod;
    	}
    	res = ((1 - res) % mod + mod) % mod;
    	return w[n] = res;
    }
    
    signed main()
    {
    	freopen("A.in" , "r" , stdin);
    	freopen("A.out" , "w" , stdout);
    	cin >> n; Init(2e6);
    	int ans = 0;
    	for(int i = 1 , r; i <= n ; i = r + 1)
    	{
    		r = min(n , n / (n / i));
    		ans = (ans + (get(r) - get(i-1) + mod) % mod * (n / i) % mod) % mod;
    	}
    	cout << ans * ans % mod << endl;
    	fclose(stdin); fclose(stdout); return 0;
    }
    
  • 相关阅读:
    H5 + 3D + AR/VR 综述
    10中典型的软件开发模型
    总线宽度VS总线带宽
    最全程序设计流程、技术、工具、交付结果【软件全生命周期】
    一幅图读懂面向对象和面向过程程序设计的区别!
    C语言实现计算器,附源码,超简单!
    request.getRequestDispatcher()的两个方法forward()/include()!!!
    关于使用ResultSet ---结果集没有当前行
    JComboBox添加item的赋值类型问题!不一致的话会导致不能更改jcombobox的选择值
    关于String的两种赋值方式
  • 原文地址:https://www.cnblogs.com/R-Q-R-Q/p/12207401.html
Copyright © 2020-2023  润新知