zoukankan      html  css  js  c++  java
  • [SDOI2014]数表

    题面就懒得放了,给个链接:LOJ
    自己的想法:

    [egin{aligned} &sum_{i=1}^nsum_{j=1}^msigma(gcd(i.j))\ &=sum_{i=1}^nsum_{j=1}^msum_{x|(i,j)}x\ &=sum_{x=1}^nsum_{i=1}^{frac{n}{x}}sum_{j=1}^frac{m}{x} end{aligned} ]

    然后就gg了,无法处理 (le a) 的限制。
    下面是正解(by Wolfycz):
    2019-09-11 21-14-36 的屏幕截图.png

    (sigma(P) = P +1)
    (aperp b,)

    [egin{aligned} sigma(ab)&=sum_{x|ab}x\ &=sum_{x|a}sum_{y|b}xy\ &=sigma(a)sigma(b) end{aligned} ]

    (a)包含(p)这个质因子

    [sigma(pa) = sigma(a) + sigma(frac{a}{low(a)})low(ap) ]

    其中 (low(x))(x) 最小质因子的指数次幂,若 (x = prod p_i^{c_i},p_1<p_2cdots) ,则 (low(x) = p_1^{c_1})
    然后就可以欧拉筛了。

    (sigma) 筛出来后,注意到 (sum_{d|T}sigma(d)mu(frac{T}{d})) 只有 (sigma(d)le a) 才会有贡献,所以我们把询问按 (a) 从小到大排序,然后把 (sigma(d) le a)(sigma(d)mu(frac{T}{d})) 插入树状数组,枚举 (d) 的倍数,就可以做到 (O(nln nlog n))

    查询就数论分块+树状数组区间求和 (O(qsqrt n log_2n)。)

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #include <fstream>
    
    #define uint unsigned int
    typedef long long LL;
    typedef unsigned long long uLL;
    
    #define SZ(x) ((int)x.size())
    #define ALL(x) (x).begin(), (x).end()
    #define MP(x, y) std::make_pair(x, y)
    #define DEBUG(...) fprintf(stderr, __VA_ARGS__)
    #define GO cerr << "GO" << endl;
    
    using namespace std;
    
    inline void proc_status()
    {
    	ifstream t("/proc/self/status");
    	cerr << string(istreambuf_iterator<char>(t), istreambuf_iterator<char>()) << endl;
    }
    
    template<class T> inline T read() 
    {
    	register T x(0);
    	register char c;
    	register int f(1);
    	while (!isdigit(c = getchar())) if (c == '-') f = -1;
    	while (x = (x << 1) + (x << 3) + (c xor 48), isdigit(c = getchar()));
    	return x * f;
    }
    
    template<typename T> inline bool chkmin(T &a, T b) { return a > b ? a = b, 1 : 0; }
    template<typename T> inline bool chkmax(T &a, T b) { return a < b ? a = b, 1 : 0; }
    
    const int maxN = 1e5;
    
    struct Query
    {
    	uint n, m, id;
    	uint ans;
    	unsigned int a;
    } q[maxN + 2];
    
    struct BIT
    {
    	unsigned int t[maxN + 2];
    	void add(int x, unsigned int y) { for (; x <= maxN; x += x & -x) t[x] += y; }
    	unsigned int query(int x) 
    	{
    		unsigned int ans = 0;
    		for (; x; x -= x & -x)
    			ans += t[x];
    		return ans;
    	}
    } T;
    
    int Q;
    bool vis[maxN + 2];
    vector<unsigned int> prime;
    pair<unsigned int, unsigned int> sigma[maxN + 2];
    unsigned int mu[maxN + 2], low[maxN + 2];
    
    void Input()
    {
    	Q = read<int>();
    	for (int i = 1; i <= Q; ++i) 
    		q[i].n = read<int>(), q[i].m = read<int>(), q[i].a = read<int>(), q[i].id = i;
    }
    
    void Init()
    {
    	sigma[1] = MP(1, 1);
    	mu[1] = 1;
    	for (register int i = 2; i <= maxN; ++i)
    	{
    		if (!vis[i])
    		{
    			mu[i] = -1;
    			low[i] = i;
    			sigma[i] = MP(1 + i, i);
    			prime.push_back(i);
    		}
    		for (register int j = 0; j < SZ(prime) && prime[j] * i <= maxN; ++j)
    		{
    			int t = prime[j] * i;
    			vis[t] = 1;
    			if (i % prime[j] == 0)
    			{
    				low[t] = low[i] * prime[j];
    				mu[t] = 0;
    				sigma[t] = MP(sigma[i].first + low[t] * sigma[i / low[i]].first, t);
    			}
    			else
    			{
    				low[t] = prime[j];
    				mu[t] = -mu[i];
    				sigma[t] = MP(sigma[i].first * sigma[prime[j]].first, t);
    			}
    		}
    	}
    	//DEBUG("%d
    ", sigma[9].first);
    	sort(sigma + 1, sigma + 1 + maxN);
    }
    
    bool cmp(const Query& A, const Query& B) { return A.a < B.a; }
    bool cmp2(const Query& A, const Query& B) { return A.id < B.id; }
    
    void Solve()
    {
    	sort(q + 1, q + 1 + Q, cmp);
    	int pos = 0;
    	for (int i = 1; i <= Q; ++i)
    	{
    		while (sigma[pos + 1].first <= q[i].a and pos < maxN)
    		{
    			pos++;
    			for (int j = 1; j * sigma[pos].second <= maxN; ++j)
    				T.add(sigma[pos].second * j, sigma[pos].first * mu[j]);
    		}
    		unsigned int ans = 0;
    		if (q[i].n > q[i].m) swap(q[i].n, q[i].m);
    		int n = q[i].n, m = q[i].m;
    		for (register int l = 1, r; l <= n; l = r + 1)
    		{
    			r = min(n / (n / l), m / (m / l));
    			ans += (T.query(r) - T.query(l - 1)) * (n / l) * (m / l);
    		}
    		q[i].ans = ans & 0x7FFFFFFF;
    	}
    	sort(q + 1, q + 1 + Q, cmp2);
    	for (int i = 1; i <= Q; ++i)
    		printf("%d
    ", q[i].ans);
    }
    
    int main() 
    {
    #ifndef ONLINE_JUDGE
    	freopen("xhc.in", "r", stdin);
    	freopen("xhc.out", "w", stdout);
    #endif
    	Input();
    	Init();
    	Solve();
    	return 0;
    }
    
  • 相关阅读:
    java泛型介绍
    JavaWeb---总结(十九)Session机制
    ServiceWorker入门介绍一
    Ehcache入门介绍一
    Hadoop入门介绍一
    给安卓端调用的短信发送接口demo
    Java开发需要注意的流程
    一些题
    省选模拟3
    省选模拟2
  • 原文地址:https://www.cnblogs.com/cnyali-Tea/p/11509925.html
Copyright © 2011-2022 走看看