bzoj2005 能量采集 gcd 容斥
2016-06-03 17:13
316 查看
ans = sigma_x(sigma_y(gcd(x,y) * 2 - 1)),1<=x<=n,1<=y<=m
枚举x,y,O(nmlogn),超时
换个角度,枚举d = gcd(x,y)
d对ans的贡献为2*d-1
若有n个(x,y)使得gcd(x,y) = d,则贡献为n * (2 * d - 1)
f(d) 表示gcd(x,y) = d 的(x,y)个数
ans = sigma(f[d] * (2 * d - 1)),1 <= d <= min(n,m)
那么问题就是求f(d)
g(d) 表示d|gcd(x,y)的(x,y)个数
则g(d) = (n / d) * (m / d)
f(d) = g(d) - f(i * d) , 2 <= i <= min(n,m) / d
反序遍历d,即min(n,m) 到 1
求f(d),累加f(d) * (2 * d - 1) 到ans
O(nlogn)
枚举x,y,O(nmlogn),超时
换个角度,枚举d = gcd(x,y)
d对ans的贡献为2*d-1
若有n个(x,y)使得gcd(x,y) = d,则贡献为n * (2 * d - 1)
f(d) 表示gcd(x,y) = d 的(x,y)个数
ans = sigma(f[d] * (2 * d - 1)),1 <= d <= min(n,m)
那么问题就是求f(d)
g(d) 表示d|gcd(x,y)的(x,y)个数
则g(d) = (n / d) * (m / d)
f(d) = g(d) - f(i * d) , 2 <= i <= min(n,m) / d
反序遍历d,即min(n,m) 到 1
求f(d),累加f(d) * (2 * d - 1) 到ans
O(nlogn)
//File Name: bzoj2005.cpp //Author: long //Mail: 736726758@qq.com //Created Time: 2016年02月12日 星期五 14时08分18秒 #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #define LL long long using namespace std; const int MAXN = 100000+5; LL f[MAXN]; void solve(int n,int m) { LL ans = 0LL; int mi = min(n,m); memset(f,0,sizeof f); for(int i=mi;i>0;i--){ f[i] = (LL)(n/i) * (m/i); for(int j=2;j<=mi/i;j++){ f[i] -= f[j*i]; } ans += f[i] * (i * 2LL - 1); } cout << ans << endl; return ; } int main() { int n,m; while(~scanf("%d %d",&n,&m)){ solve(n,m); } return 0; }
相关文章推荐
- java的Calendar类如何获取当前时间的时分秒以及毫秒。
- spring通过注解配置Bean
- 集成环信支持ipv6
- Hibernate-HQL查询(2)子查询、连接查询
- 安卓矢量图的制作
- FreeSwitch:四、FreeSwitch 常用命令
- Weservice以后会有用吧
- 1083. List Grades (25) PAT
- ABAP 7.4新特性(二):NEW 操作符
- NOIP2006 最大和
- 正则表达式
- C# Socket网络编程精华篇
- 个人总结
- android dialog
- Hibernate-HQL查询(1)基本查询、命名参数
- 2016-6-3基础总结
- 多线程
- 欢迎使用CSDN-markdown编辑器
- Call to localhost/127.0.0.1:9000 failed on connection exception错误。
- Android-TV-Frame v1.4.0 发布,Android TV 开发框架