本文主要是介绍HDU 1796 How many integers can you find,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
链接:http://acm.hdu.edu.cn/showproblem.php?pid=1796
How many integers can you find
Time Limit: 12000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 5612 Accepted Submission(s): 1608
Problem Description
Input
Output
For each case, output the number.
Sample Input
12 2 2 3
Sample Output
7
#include <iostream>
#include <cstdio>
#include <string>
#include <cmath>
#include <iomanip>
#include <ctime>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#include <set>
#include <map>
//#pragma comment(linker, "/STACK:102400000, 102400000")
using namespace std;
typedef unsigned int li;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const double pi = acos(-1.0);
const double e = exp(1.0);
const double eps = 1e-8;
const int maxm = 15; // 集合最大计数
int num[maxm]; // m个数的集合
int n, m, cnt; // 给定数n,集合计数m,不为零的m集合计数
int ans; // 最后所求结果int gcd(int a, int b); // 求最大公约数
int lcm(int a, int b); // 求最小公倍数
void dfs(int index, int common, int sign); // 利用深搜展现容斥原理int main()
{ios::sync_with_stdio(false);while (~scanf("%d%d", &n, &m)){int x; // 集合元素cnt = 0;while (m--){scanf("%d", &x);if (0 == x) // 集合元素可能含有零,丢弃零continue;num[cnt++] = x; // 不为零的元素存入集合}ans = 0; // 初始化最后所求结果for (int i=0; i<cnt; i++)dfs(i, num[i], 1); // 枚举m集合中非零元素进行深搜printf("%d\n", ans);}return 0;
}int gcd(int a, int b)
{ // 欧几里得算法/辗转相除法return b ? gcd(b, a%b) : a;
}int lcm(int a, int b)
{ // 这样写,有利于防止中间过程溢出return a/gcd(a, b)*b;
}void dfs(int index, int common, int sign)
{ // 集合元素的索引,最小公倍数,符号判断(容斥公式中的奇数项加偶数项减)common = lcm(num[index], common);if (sign & 1) // 奇数项加ans += (n-1)/common; // 小于n的数,所以用n-1else // 偶数项减ans -= (n-1)/common;for (int i=index+1; i<cnt; ++i)dfs(i, common, sign+1); // 一层是找出一个元素的子集最小公倍数的计数// 两层是找出两个元素的子集最小公倍数的计数// 以此类推,所有子集最小公倍数的计数都找出
}
这篇关于HDU 1796 How many integers can you find的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!