zoukankan      html  css  js  c++  java
  • 【51nod】1227 平均最小公倍数

    题解

    这个故事告诉们数论函数不要往分式上跑,你推不出来
    好久没推式子了这么明显的转化我都忘了= =

    首先(A(n) = frac{1}{n} sum_{i = 1}^{n} frac{i * n}{gcd(i,n)})
    然后显然可以把n消掉
    (A(n) = sum_{i = 1}^{n} frac{i}{gcd(i,n)})
    改为枚举约数
    (A(n) = sum_{d = 1}^{n} frac{1}{d}sum_{i = 1}^{n} i [gcd(i,n) == d])
    (A(n) = sum_{d | n} sum_{i = 1}^{frac{n}{d}} i [gcd(i,frac{n}{d}) == 1])
    有个欧拉函数的性质是,小于这个数的且与这个数互质的数的和是
    (frac{n phi(n) + [n = 1]}{2}) 挺好理解的,因为一个与n互质的数p,n - p也和n互质
    (frac{n phi(n) + [n = 1]}{2} = sum_{i = 1}^{n} i [gcd(i,n) == 1])
    (A(n) = frac{1}{2} (sum_{d | n} frac{n}{d} phi(frac{n}{d}) + 1))

    (F(n) = sum_{i = 1}^{n} A(i))
    (F(n) = frac{1}{2} (sum_{i = 1}^{n} sum_{d | i} frac{i}{d} phi(frac{i}{d}) + n))
    (F(n) = frac{1}{2} (sum_{i = 1}^{n} sum_{d | i} d phi(d) + n))
    (F(n) = frac{1}{2} (sum_{i = 1}^{n} sum_{d = 1}^{frac{n}{i}} d phi(d) + n))

    我们发现这个东西可以构造卷积啊
    (sum_{d = 1}^{n} d phi(d))
    卷上一个(Id(x) = x^{2})
    那么我们就有
    (sum_{i = 1}^{n} i^2 = sum_{i = 1}^{n} sum_{d | i}d phi(d) frac{i}{d})
    (sum_{i = 1}^{n} i^2 = sum_{k = 1}^{n} k sum_{d = 1}^{frac{n}{k}}d phi(d))
    那么就有
    (S(n) = frac{n(n +1)(2n + 1)}{6} - sum_{i = 2}^{n} i S(lfloor frac{n}{i} floor))
    然后用数论分块求(F(n))即可

    题解

    #include <iostream>
    #include <cstdio>
    #include <vector>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    #include <map>
    //#define ivorysi
    #define pb push_back
    #define space putchar(' ')
    #define enter putchar('
    ')
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define mo 974711
    #define MAXN 1000000
    #define RG register
    using namespace std;
    typedef long long int64;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;char c = getchar();T f = 1;
    	    while(c < '0' || c > '9') {
    			if(c == '-') f = -1;
    			c = getchar();
    	    }
    	    while(c >= '0' && c <= '9') {
    		res = res * 10 + c - '0';
    		c = getchar();
        }
        res *= f;
    }
    template<class T>
    void out(T x) {
        if(x < 0) {putchar('-');x = -x;}
        if(x >= 10) {
    		out(x / 10);
        }
        putchar('0' + x % 10);
    }
    int N;
    const int MOD = 1000000007;
    struct node {
    	int x,v,next;
    }E[100006];
    int head[mo + 5],sumE,Inv2,Inv6;
    int prime[MAXN + 5],tot,S[MAXN + 5],phi[MAXN + 5];
    bool nonprime[MAXN + 5];
    int inc(int a,int b) {
    	a = a + b;
    	if(a >= MOD) a -= MOD;
    	return a;
    }
    int mul(int a,int b) {
    	return 1LL * a * b % MOD;
    }
    void add(int u,int x,int v) {
    	E[++sumE].x = x;E[sumE].v = v;E[sumE].next = head[u];
    	head[u] = sumE;
    }
    void Insert(int x,int v) {
    	add(x % mo,x,v);
    }
    int Query(int x) {
    	int u = x % mo;
    	for(int i = head[u] ; i ; i = E[i].next) {
    		if(E[i].x == x) return E[i].v;
    	}
    	return -1;
    }
    int f(int x) {
    	if(x <= MAXN) return S[x];
    	int c = Query(x);
    	if(c != -1) return c;
    	int res = 0;
    	for(int i = 2 ; i <= x ; ++i) {
    		int r = x / (x / i);
    		res = inc(res,1LL * (r - i + 1) * (r + i) / 2 % MOD * f(x / i) % MOD);
    		i = r;
    	}
    	res = inc(1LL * x * (x + 1) % MOD * (2 * x + 1) % MOD * Inv6 % MOD,MOD - res);
    	Insert(x,res);
    	return res;
    }
    int calc(int x) {
    	int res = 0;
    	for(int i = 1 ; i <= x ; ++i) {
    		int r = x / (x / i);
    		res = inc(res,mul(r - i + 1,f(x / i)));
    		i = r;
    	}
    	res = inc(res,x);
    	res = mul(res,Inv2);
    	return res;
    }
    void Solve() {
    	phi[1] = 1;S[1] = 1;
    	for(int i = 2 ; i <= MAXN ; ++i) {
    		if(!nonprime[i]) {
    			prime[++tot] = i;
    			phi[i] = i - 1;
    		}
    		for(int j = 1 ; j <= tot ; ++j) {
    			if(prime[j] > MAXN / i) break;
    			nonprime[prime[j] * i] = 1;
    			if(i % prime[j] == 0) {phi[i * prime[j]] = phi[i] * prime[j];break;}
    			else phi[i * prime[j]] = phi[i] * (prime[j] - 1);
    		}
    		S[i] = inc(S[i - 1],mul(phi[i],i));
    	}
    	Inv2 = (MOD + 1) / 2;
    	Inv6 = 1LL * Inv2 * (MOD + 1) / 3 % MOD; 
    	int a,b;
    	read(a);read(b);
    	out(inc(calc(b),MOD - calc(a - 1)));enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
       	Solve();
        return 0;
    }
    
  • 相关阅读:
    swagger-ui 系统配置过程(基于spring+springmvc+swagger+springfox配置 web-api 管理系统)
    如何简单扫描整理
    C#双面打印解决方法(打印wordexcel图片)
    MODI出现ORC RUNNING ERROR的解决方法
    EMGU 2.9.X在VS2010下调试真正靠谱的配置
    如何解决The underlying provider failed on Open问题
    shell编程之——cat /dev/null作用
    docker 容器的设置2
    docker 容器的设置1
    ssl证书生成与转换(pfx, pem, key, crt)
  • 原文地址:https://www.cnblogs.com/ivorysi/p/9157831.html
Copyright © 2011-2022 走看看