HDU 5514
2016-03-14 11:00
363 查看
题意: 给你 N 个数 和 一个 M;
对于 每一个 Ni , 乘以 K 取摸 M 都有一个 集合, 把所有集合合并, 求和
Σ ai ( ai → K * Ni % M )
思路 : 最开始 直接求一边gcd , 然后容斥。。。。 结果状态有 2 ^ (1e4)....
反着求 M 的约数, 然后记录要用到的约数, 对于这些进行容斥就好了(不能状压)
对于 每一个 Ni , 乘以 K 取摸 M 都有一个 集合, 把所有集合合并, 求和
Σ ai ( ai → K * Ni % M )
思路 : 最开始 直接求一边gcd , 然后容斥。。。。 结果状态有 2 ^ (1e4)....
反着求 M 的约数, 然后记录要用到的约数, 对于这些进行容斥就好了(不能状压)
#include<bits/stdc++.h> using namespace std; typedef long long LL; const int maxn = 1e5 + 131; LL gcd(LL a, LL b){ return b == 0 ? a : gcd(b, a % b); } LL P[maxn], cnt; void GetP(LL m){ cnt = 0; for(LL i = 1; i <= sqrt(m); ++i) { if(m % i == 0) { P[cnt++] = i; if(i * i != m) P[cnt++] = m / i; } } sort(P,P+cnt); } LL Vis[maxn], Num[maxn]; int main() { int T; scanf("%d", &T); for(int kase = 1; kase <= T; ++kase) { LL n, m; scanf("%lld %lld", &n, &m); GetP(m); LL u; memset(Vis,0, sizeof(Vis)); memset(Num,0, sizeof(Num)); for(int i = 0; i < n; ++i) { scanf("%lld", &u); LL tmp = gcd(u, m); for(LL j = 0; j < cnt; ++j) { if(P[j] % tmp == 0) Vis[j] = 1; } } //cout << P[cnt - 1 ] << endl; Vis[cnt -1] = 0; LL Ans = 0; for(LL i = 0; i < cnt; ++i) // 容斥 { if(Vis[i] != Num[i]) { LL tmp = m / P[i], D = Vis[i] - Num[i]; Ans += (tmp + 1) * tmp / 2 * P[i] * D; for(LL j = i; j < cnt; ++j) { if(P[j] % P[i] == 0) Num[j] += D; } } } printf("Case #%d: %lld\n", kase, Ans); } }
相关文章推荐
- 改变对象的key的名称
- MyEclipse性能优化
- Light OJ 1102
- Light OJ 1095
- Light OJ 1058
- Light OJ 1214
- JSTL获取Parameter参数
- C语言——结构体与联合体
- Mybatis高级应用
- 4154: [Ipsc2015]Generating Synergy K-D tree
- java处理高并发高负载类网站的优化方法
- Android NDK UPX加固
- 【Chromium中文文档】Chromium如何展示网页
- AJAX实现跨域的三种种方法(代理,JSONP,XHR2)
- Redhat5.8 环境下编译安装 Redis 并将其注册为系统服务
- Light OJ 1148
- Light OJ 1116
- Light OJ 1078
- Light OJ 1020
- Light OJ 1012