HDU 1796 How many integers can you find 解题报告(数论)
来源:互联网 发布:数控编程的步骤 编辑:程序博客网 时间:2024/05/29 09:53
How many integers can you find
Time Limit: 12000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 3505 Accepted Submission(s): 982
Problem Description
Now you get a number N, and a M-integers set, you should find out how many integers which are small than N, that they can divided exactly by any integers in the set. For example, N=12, and M-integer set is {2,3}, so there is another set {2,3,4,6,8,9,10}, all the integers of the set can be divided exactly by 2 or 3. As a result, you just output the number 7.
Input
There are a lot of cases. For each case, the first line contains two integers N and M. The follow line contains the M integers, and all of them are different from each other. 0<N<2^31,0<M<=10, and the M integer are non-negative and won’t exceed 20.
Output
For each case, output the number.
Sample Input
12 22 3
Sample Output
7
Author
wangye
解题报告:0 - n 间能被集合中整除的数有多少个。暴力肯定不行,最大的n是2^31。
思考一下,0 - n 间能被4整除的数有多少个?n / 4 个。
那么 0 - n 间能被6整除的数有多少个? n / 6 个。
而 0 - n 间能被{4, 6}整除的数应该是 n / 4 + n / 6 - n / lcm(4, 6) 个。因为有重复。
重复此过程,集合中数字最多有10个,可以用数组存储每次lcm的值。
AC代码如下:
#include <cstring>#include <cstdio>#include <algorithm>using namespace std;typedef long long LL;int array[21];int last[10000];int top;int gcd(int a, int b){return b == 0 ? a : gcd(b, a%b);}LL lcm(int a, int b){return (LL)a / gcd(a, b) * b;}int main(){#ifdef ACMfreopen("in.txt", "r", stdin);#endifint n, m;while (~scanf("%d%d", &n, &m)){n--;top = 0;for (int i = 0; i < m; i++){scanf("%d", array + i);if (array[i] == 0) m--, i--;}sort(array, array + m);int newM = 0;for (int i = 0; i < m; i++){bool ok = true;for (int j = 0; j < i; j++){if (array[i] % array[j] == 0){ok = false;break;}}if (ok){array[newM++] = array[i];}}m = newM;int res = 0;for (int i = 0; i < m; i++){int a = array[i];res += n / a;int newTop = top;last[newTop++] = a;for (int j = 0; j < top; j++){LL t;if (last[j] < 0)t = lcm(a, -last[j]);elset = -lcm(a, last[j]);if (t <= n){last[newTop++] = (int)t;res += n / (int)t;}}top = newTop;}printf("%d\n", res);}}
上面这段不是太好看,但是偶然间发现这段代码是杭电上最快的= =,0MS
标准点的容斥原理应该这么写:
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;int num[22];int gcd(int a, int b){ return b==0?a:gcd(b, a%b);}int lcm(int a, int b){ return a/gcd(a,b)*b;}int main(){ int n, m; while(~scanf("%d%d", &n, &m)) { n--; for(int i=0; i<m; i++) { scanf("%d", num+i); if(num[i]==0) m--,i--; } int ans = 0; for(int i=1;i<(1<<m);i++) { long long tmp = 1; bool flag = false; for(int j=0;j<m;j++) if(i&(1<<j)) tmp = lcm(tmp, num[j]), flag = !flag; if(flag) ans += n/tmp; else ans -= n/tmp; } printf("%d\n", ans); }}
因为多次重复lcm,所有代码的效率很慢。时效640MS。
另外,本题和ZOJ 2836 近乎相同,将scanf m,n 的顺序交换即可。
0 0
- HDU 1796 How many integers can you find 解题报告(数论)
- HDU 1796 How many integers can you find (数论之容斥)
- How many integers can you find HDU
- hdu 1796 How many integers can you find
- HDU 1796 How many integers can you find
- HDU 1796 How many integers can you find
- HDU 1796 How many integers can you find
- hdu 1796 How many integers can you find
- HDU 1796 How many integers can you find
- HDU 1796 How many integers can you find
- hdu-1796-How many integers can you find(容斥)
- HDU 1796 How many integers can you find 【容斥】
- How many integers can you find (HDU 1796)
- HDU 1796 How many integers can you find
- hdu 1796 How many integers can you find【二进制写容斥】
- HDU 1796 How many integers can you find
- HDU 1796 How many integers can you find(容斥原理)
- hdu 1796 How many integers can you find(容斥定理)
- 会走了才会跑
- google map api key申请
- java解决中文乱码的几种情况
- 关于java Exception error runtimeException 还有非runtimeException
- Flex中使用HTTPService向后发送请求,参数中如何使用URL的保留字符(问号、百分号)
- HDU 1796 How many integers can you find 解题报告(数论)
- 使用structs2进行ognl进行各种html元素输入数据
- PAT basic 1015 : 德才论
- Android中shape的解析
- HBase伪分布式安装的简单步骤记录
- ubuntu修改主机名
- linux trap的翻译问题
- poj 1852 Ants_贪心
- 每天一算法(一)——用链表实现加减乘运算