zoukankan      html  css  js  c++  java
  • P1447 [NOI2010]能量采集

    Link


    首先我们要求的是这个柿子:

    (displaystyle sum_{i=1}^{n} sum_{j=1}^{m} 2 imes gcd(i,j) - 1)

    (2)(1) 提出来,变成:

    (displaystyle (2 imes sum_{i=1}^{n} sum_{j=1}^{m} gcd(i.j)) - n imes m)

    我们主要解决得是这个柿子:

    (displaystyle sum_{i=1}^{n}sum_{j=1}^{m} gcd(i,j))

    接下来就到了我们的颓柿子的时间啦。

    先枚举一个 (d) ,变成

    (displaystyle sum_{d = 1}^{min(n,m)} dsum_{i = 1}^{n} sum_{j=1}^{m} [gcd(i,j) == d])

    把后面的那两个求和提一个 (d) 变成:

    (displaystylesum_{d =1}^{min(n,m)} d sum_{i=1}^{nover d}sum_{j=1}^{mover d} [gcd(i,j) == 1])

    然后,我们可以有莫比乌斯反演得到一个柿子:

    ([gcd(i,j) == 1] = displaystylesum_{dmid i,d mid j} mu(d))

    把这个柿子带回去可得

    (displaystylesum_{d=1}^{min(n,m)} d sum_{i=1}^{nover d}sum_{j=1}^{mover d} sum_{pmid i,pmid j}mu(p))

    交换一下求和顺序,先枚举 (p) 可得: (注意枚举(p) 的上限是 (min(n,m) over d) ,交换一下求和顺序,上限也要改变):

    (displaystylesum_{d=1}^{min(n,m)}d sum_{p=1}^{min({nover d},{mover d})}mu(p) sum_{i=1}^{nover d} [pmid i] sum_{j=1}^{mover d} [pmid j])

    因为 (1- {nover d}) 中能被 (p) 整除的数有 (n over {dp}) 个,所以后面的枚举 (i)(j) 的柿子可以改变一下,变成:

    (displaystylesum_{d=1}^{min(n,m)}dsum_{p=1}^{min({nover d},{mover d})}mu(p) sum_{i=1}^{nover dp} sum_{j=1}^{mover dp})

    也就是 :

    (displaystyle sum_{d=1}^{min(n,m)} d sum_{p=1}^{min({nover d},{m over d})}mu(p) lfloor {nover dp} floorlfloor{m over dp} floor)

    运用一个技巧 ,设 (Q = d imes p) ,则 (p = {Q over d}),把所有的 (p) 都替换掉,改为枚举 (Q),变成:

    (displaystylesum_{d=1}^{min(n,m)}d sum_{Q=1}^{min(n,m)}mu({Qover d}) lfloor {n over Q} floorlfloor{mover Q} floor)

    至于为什么第二个求和的上限为 (min(n,m)),因为 (p in{min({nover d},{mover d})})(Q) 的取值范围要在 (p) 的基础上乘个 (d) 变成 (min(n,m))

    交换一下枚举顺序,先枚举一下 (Q) 变为

    (displaystylesum_{Q=1}^{min(n,m)}sum_{dmid Q}^{min(n,m)} d imes mu({Q over d}) lfloor {n over Q} floor lfloor {m over Q} floor)

    因为 (mu) 的定义域是整数所以 (Qover d) 也需要是整数,也就是 (Qmid d)

    后面 可以看成是:

    (displaystylesum_{Q=1}^{min(n,m)}sum_{d mid Q}^{min(n,m)}id(d) * mu({Qover d})lfloor{nover Q} floorlfloor{mover Q} floor)

    又因为 (id * mu = phi), 后面的可以写成卷积的形式,变成:

    (displaystylesum_{Q=1}^{min(n,m)} phi(Q) lfloor{n over Q} floorlfloor{m over Q} floor)

    这个我们就可以做到 O(n) 的回答了。

    先预处理出 (phi) 函数的值,然后根据上面的柿子计算出答案就可以啦;

    Code

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define int long long
    const int N = 1e5+10;
    int n,m,ans,tot,phi[N],prime[N];
    bool check[N];
    inline int read()
    {
    	int s = 0,w = 1; char ch = getchar();
    	while(ch < '0' || ch > '9'){if(ch == '-') w = -1; ch = getchar();}
    	while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0'; ch = getchar();}
    	return s * w;
    }
    void YYCH()//预处理出φ函数的值
    {
    	phi[1] = 1;
    	for(int i = 2; i <= N-5; i++)
    	{
    		if(!check[i])
    		{
    			prime[++tot] = i;
    			phi[i] = i-1;
    		}
    		for(int j = 1; j <= tot && i * prime[j] <= N-5; j++)
    		{
    			check[i * prime[j]] = 1;
    			if(i % prime[j] == 0)
    			{
    				phi[i * prime[j]] = phi[i] * prime[j];
    				break;
    			}
    			else
    			{
    				phi[i * prime[j]] = phi[i] * phi[prime[j]];
    			}
    		}
    	}
    }
    int calc(int d)
    {
    	return (n/d) * (m/d);
    }
    signed main()
    {
    	n = read(); m = read();
    	if(n > m) swap(n,m); YYCH();
    	for(int i = 1; i <= n; i++)
    	{
    		ans += phi[i] * calc(i);//计算答案
    	}
    	ans = ans * 2 - n * m;
    	printf("%lld
    ",ans);
    	return 0;
    }
    

    Update: 总算写完了这一大堆柿子,累死我了

  • 相关阅读:
    网页信息抓取 Jsoup的不足之处 httpunit
    spring boot @ConfigurationProperties
    git冲突解决方案 Intellij IDEA
    HTTP 和 Socket 区别
    java.lang.reflect.Method
    dubbo hessian+dubbo协议
    4、注解反射生成SQL语句
    3、解析注解
    2、自定义注解
    1、JDK自带注解
  • 原文地址:https://www.cnblogs.com/genshy/p/13668246.html
Copyright © 2011-2022 走看看