hdu5514Frogs(2015ACM-ICPC沈阳赛区F题)
这题很容易转化到一个容斥计数问题。而用指数复杂度的枚举计数法显然会挂,只能考虑别的方法。
首先将a[i]用gcd(a[i], m)替换,排序去重后得到一组m的约数,而m不超过1e9,因此m的所有约数最多在1000左右。
假设数组a只含有2,3两个元素,那么显然答案应该是f(2) + f(3) - f(6),f(i)表示只有i的情况下的答案。
2和3的系数是1,6的系数是-1,其余系数为0。
根据容斥原理:对于某个特定的约数,若存在数组a的一个子集其lcm为该约数,那么若集合元素个数为偶数,贡献-1,若为奇数,贡献1。
而最终的答案一定由所有约数合成,其系数取值{-1,0,1}。
因此我们考虑数组a的前m个数,其对应的系数分布是可以确定的。
加入第m+1个数时,显然新的集合必然由原集合的子集并上新元素得到,分别考虑m的所有约数k,其对应的系数为op(k)
若op(k)为-1,则说明偶数子集的个数比奇数子集的个数多1,若我们添如新元素x,则恰好使得奇数子集个数比偶数多1,但此时贡献
不是对k的,而是对lcm(k, x),用公式表示就是:
op(lcm(k, x)) += op(k) * (-1).
其余情形类似。
最终答案是ans = sigma(op(i) * f(i)), i | m.
这样我们只需最多进行1000次遍历就可使得元素个数加一,总复杂度约为O(1e6)。
- #include <cstdio>
- #include <cstring>
- #include <algorithm>
- #include <map>
- #include <string>
- #include <vector>
- #include <set>
- #include <cmath>
- #include <ctime>
- #include <cassert>
- #define lson (u << 1)
- #define rson (u << 1 | 1)
- #define cls(i, j) memset(i, j, sizeof i)
- #pragma comment(linker, "/STACK:102400000,102400000")
- using namespace std;
- typedef __int64 ll;
- const double eps = 1e-;
- const double pi = acos(-1.0);
- const int maxn = 1e4 + ;
- const int maxm = 4e4 + ;
- const int inf = 0x3f3f3f3f;
- const ll linf = 0x3fffffffffffffff;
- const ll mod = 1e9 + ;
- map<ll, int> mapi;
- int n;
- ll a[maxn], m;
- int prime[maxm], k;
- bool vis[maxm];
- ll fact[maxn], nf;
- int cnt[maxn];
- ll table[maxn], nt;
- int op[maxn];
- int op1[maxn];
- ll ans;
- ll gcd(ll a, ll b) { return !b ? a : gcd(b, a % b); }
- void init(){
- cls(vis, );
- k = ;
- for(int i = ; i < maxm; i++){
- if(vis[i]) continue;
- prime[k++] = i;
- for(int j = i * ; j < maxm; j += i) vis[j] = ;
- }
- }
- void dfs(int next, ll num){
- if(next >= nf){
- table[nt++] = num;
- mapi[num] = nt - ;
- return;
- }
- ll tem = num;
- for(int i = ; i <= cnt[next]; i++){
- dfs(next + , tem);
- tem *= fact[next];
- }
- }
- ll f(ll num){
- ll tem = (m - ) / num;
- return tem * (tem + ) / * num;
- }
- void factorize(){
- nf = ;
- ll m1 = m;
- int mid = (int)sqrt(m);
- for(int i = ; prime[i] <= mid; i++){
- if(m % prime[i]) continue;
- fact[nf++] = prime[i];
- cnt[nf - ] = ;
- while(m % prime[i] == ) ++cnt[nf - ], m /= prime[i];
- mid = (int)sqrt(m);
- }
- if(m != ) fact[nf++] = m, cnt[nf - ] = ;
- m = m1;
- }
- ll solve(){
- mapi.clear();
- int n1 = ;
- for(int i = ; i < n; i++){
- ll tem = a[i] % m;
- if(!tem) continue;
- a[n1++] = gcd(m, tem);
- }
- n = n1;
- sort(a, a + n);
- n = unique(a, a + n) - a;
- cls(vis, );
- for(int i = ; i < n; i++){
- for(int j = i + ; j < n; j++){
- if(a[i] % a[j] == ) vis[i] = ;
- else if(a[j] % a[i] == ) vis[j] = ;
- }
- }
- n1 = ;
- for(int i = ; i < n; i++) if(!vis[i]) a[n1++] = a[i];
- n = n1;
- sort(a, a + n);
- factorize();
- nt = ;
- dfs(, );
- cls(op, );
- ans = ;
- for(int i = ; i < n; i++){
- cls(op1, );
- for(int j = ; j < nt; j++){
- ll tem = a[i] / gcd(a[i], table[j]) * table[j];
- if(tem >= m) continue;
- op1[mapi[tem]] += -op[j];
- }
- ++op1[mapi[a[i]]];
- for(int j = ; j < nt; j++) op[j] += op1[j];
- }
- // for(int i = 0; i < nt; i++) printf("%d ", op[i]);
- // puts("");
- for(int i = ; i < nt; i++) ans += op[i] * f(table[i]);
- return ans;
- }
- int main(){
- // freopen("in.txt", "r", stdin);
- int T, kase = ;
- init();
- scanf("%d", &T);
- while(T--){
- scanf("%d%I64d", &n, &m);
- for(int i = ; i < n; i++) scanf("%I64d", &a[i]);
- ll ans = solve();
- printf("Case #%d: %I64d\n", ++kase, ans);
- }
- return ;
- }
hdu5514Frogs(2015ACM-ICPC沈阳赛区F题)的更多相关文章
- 2015ACM/ICPC亚洲区长春站 F hdu 5533 Almost Sorted Array
Almost Sorted Array Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Ot ...
- HDU 5901 Count primes (1e11内的素数个数) -2016 ICPC沈阳赛区网络赛
题目链接 题意:求[1,n]有多少个素数,1<=n<=10^11.时限为6000ms. 官方题解:一个模板题, 具体方法参考wiki或者Four Divisors. 题解:给出两种代码. ...
- hdu 4461 第37届ACM/ICPC杭州赛区I题
题意:给两个人一些棋子,每个棋子有其对应的power,若b没有或者c没有,或者二者都没有,那么他的total power就会减1,total power最少是1,求最后谁能赢 如果b或c出现的话,fl ...
- zoj 3662 第37届ACM/ICPC长春赛区H题(DP)
题目:给出K个数,使得这K个数的和为N,LCM为M,问有多少种 f[i][j][k]表示选i个数,总和为j,最小公倍数为k memery卡的比较紧,注意不要开太大,按照题目数据开 这种类型的dp也是第 ...
- hdu 4463 第37届ACM/ICPC杭州赛区K题 最小生成树
题意:给坐标系上的一些点,其中有两个点已经连了一条边,求最小生成树的值 将已连接的两点权值置为0,这样一定能加入最小生成树里 最后的结果加上这两点的距离即为所求 #include<cstdio& ...
- 2015 ICPC 沈阳站M题
M - Meeting Time Limit:6000MS Memory Limit:262144KB 64bit IO Format:%I64d & %I64u Submit ...
- HDU 5532 / 2015ACM/ICPC亚洲区长春站 F.Almost Sorted Array
Almost Sorted Array Problem Description We are all familiar with sorting algorithms: quick sort, mer ...
- 2016 ICPC大连站---F题 Detachment
题意:输入一个x,将x拆分成一些小的数(这些数不能相同,即x=a1+a2+...... ai!=aj when i!=j),然后这些数相乘得到一个成积(s=a1*a2*......),求最大的乘积 ...
- HDU 5894 hannnnah_j’s Biological Test (组合数学) -2016 ICPC沈阳赛区网络赛
题目链接 #include <map> #include <queue> #include <math.h> #include <stdio.h> #i ...
随机推荐
- swift语言实战晋级-第9章 游戏实战-跑酷熊猫-9-10 移除平台与视差滚动
9.9 移除场景之外的平台 用为平台是源源不断的产生的,如果不注意销毁,平台就将越积越多,虽然在游戏场景中看不到.几十个还看不出问题,那几万个呢?几百万个呢? 所以我们来看看怎么移除平台,那什么样的平 ...
- MAC开发NDK非常的简单
转自:http://www.cnblogs.com/jarrah/archive/2013/03/15/2961892.html 附带CDT的下载:http://www.eclipse.org/cdt ...
- ajax常用参数
url: 要求为String类型的参数,(默认为当前页地址)发送请求的地址.前台跳转到后台 请求参数:前台向后台传数据 回调函数:回调函数就是一个自定义的函数在发生特定的事件的时候调用来处理这个事件 ...
- struts复合类型传值(对象传值)
01:导包,配置web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app version ...
- linux env
.Linux的变量种类 按变量的生存周期来划分,Linux变量可分为两类: 1.1 永久的:需要修改配置文件,变量永久生效. 1.2 临时的:使用export命令声明即可,变量在关闭shell时失效. ...
- <构建之法>之一至二章
身在大学,却想起了在高中的生活和初中的生活,特别是初中的生活,为什么这么说呢!因为<构建之法>,看了其中的两章的内容,为什么想到了初中和高中的生活呢,因为在高中和初三的时候看的最多的就是课 ...
- 南阳oj27题
水池数目 时间限制:3000 ms | 内存限制:65535 KB 难度:4 描述 南阳理工学院校园里有一些小河和一些湖泊,现在,我们把它们通一看成水池,假设有一张我们学校的某处的地图,这个地图上 ...
- 夺命雷公狗jquery---1选择元素的3种方法
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- PAT乙级 1029. 旧键盘(20)
1029. 旧键盘(20) 时间限制 200 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 旧键盘上坏了几个键,于是在敲一段文字的 ...
- PAT乙级 1017. A除以B (20)
1017. A除以B (20) 时间限制 100 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 本题要求计算A/B,其中A是不超过 ...