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

    题目链接

    Solution [NOI2010]能量采集

    题目大意:在平面直角坐标系内有(n * m)个点((x,y))(x in [1,n])(y in [1,m]),在((0,0))位置有一台机器,如果机器和点((x,y))之间的连线上有(k)个点的话那么就有(2k-1)的能量损失,给定(n,m)求能量损失之和

    莫比乌斯反演


    分析:

    这题和[SDOI2008]仪仗队这题比较相似

    假设我们可以看到一个点((x,y)),那么((lambda x,lambda y)),这个点我们是看不见的,换句话说,只有(gcd(x,y)=1)的点我们才看得见。进一步,如果(gcd(x,y)=k),那么从原点到点((x,y))的线段上有(k)个点

    也就是说我们求的是这玩意儿(sum_{i=1}^nsum_{j=1}^m(2 imes gcd(i,d)-1))

    莫比乌斯反演就好了qaq

    #include <iostream>
    #include <algorithm>
    #include <vector>
    using namespace std;
    typedef long long ll;
    const int maxn = 1e5 + 100;
    int vis[maxn],n,m;
    ll phi[maxn],ans;
    vector<int> pri;
    inline void sieve(){
    	phi[1] = 1;
    	for(int i = 2;i < maxn;i++){
    		if(!vis[i]){
    			pri.push_back(i);
    			phi[i] = i - 1;
    		}
    		for(int x : pri){
    			if(1ll * i * x >= maxn)break;
    			vis[i * x] = 1;
    			if(i % x)phi[i * x] = phi[i] * phi[x];
    			else{
    				phi[i * x] = phi[i] * x;
    				break;
    			}
    		}
    	}
    	for(int i = 1;i < maxn;i++)
    		phi[i] += phi[i - 1];
    }
    int main(){
    	sieve();
    	cin >> n >> m;
    	for(int r,l = 1;l <= min(n,m);l = r + 1){
    		r = min(min(n,m),min(n / (n / l),m / (m / l)));
    		ans += 2ll * (phi[r] - phi[l - 1]) * (n / l) * (m / l);
    	}
    	ans -= 1ll * n * m;
    	cout << ans << '
    ';
    	return 0;
    }
    
  • 相关阅读:
    java学习笔记(4)多态
    scala学习笔记(1)
    java复习(3)继承下
    java复习(3)继承
    java复习(2)
    java中常见的异常种类
    数组的内存结构
    Castle ActiveRecord学习(一)简介
    OAuth2.0 Owin 授权问题
    将对象转为json,加入到HttpResponseMessage中
  • 原文地址:https://www.cnblogs.com/colazcy/p/12350277.html
Copyright © 2011-2022 走看看