Ural 1091 Tmutarakan Exams [容斥原理]

来源:互联网 发布:linux 查看gpu显存 编辑:程序博客网 时间:2024/05/16 08:02

题目链接·:http://acm.timus.ru/problem.aspx?space=1&num=1091

题目意思,让你在1 - s中找k个数的公因子大于1,问有多少种这样的组合。。。(1 <= k <= s <= 50)。

分析:

我们要找的k个的公因子大于1。而且k,s       小于50。

我们可以直接枚举大于1的素公因子。求出以该素因子为因子的数有多少个,然后组合就好。。

一开始,我就是这么单纯的认为是这样的。。仅仅是这样的。。。- - 。。

后来发现WA的已发不可收拾。。后来才知道,仅仅这样做的话肯定会多加了一部分。多加那部分呢??

比如:k = 2 , s = 20。

2:2,4,6,8,10,12,14,16,18,20

3:3,6,9,12,15,18

5:5,10,15,20,

7:7,14

我们知道2:6,12,18

              3:6,12,18 这两种在组合的时候就会重复。

我们可以发现他们都是6的倍数。也就是说他们的公因子都为6 = 2 * 3。。去掉这一类的数就好。。。

容斥原理还需要更多的去理解。。。

Code:

#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>#include <cmath>using namespace std;const int N = 20;int f[N] = {2, 3, 5, 7, 11, 13, 17, 19, 23};int C(int n, int m){    m = min(m, n - m);    int ans = 1;    for(int i = 1;  i <= m; i ++){        ans = ans * (n - i + 1);        ans = ans / i;    }    return ans;}int main(){    int k, s;    while(cin >> k >> s){        int ans = 0;        for(int i = 0; i < 9; i ++){            if(s / f[i] >= k)            ans += C(s / f[i], k);        }        for(int i = 0; i < 9; i ++){            for(int j = i + 1; j < 9; j ++)            {                if(s / (f[i] * f[j]) >= k){                    ans -= C(s / (f[i] * f[j]), k);                }            }        }        if(ans <= 10000) cout << ans << endl;        else cout << "10000" << endl;    }    return 0;}

------>

Code(二进制写法):)

#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>#include <cmath>using namespace std;const int N = 20;const int prime[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29};int C(int n, int m){    if(n < m) return 0;    int ans = 1;    m = min(m, n - m);    for(int i = 1; i <= m; i ++){        ans = ans * (n - i  + 1);        ans = ans / i;    }    return ans ;}int solve(int k , int s){    int ans = 0, top = 0;    for(int i = 0; i < 10; i ++){        if(s / prime[i] < k){            top = i;            break;        }    }    for(int i = 1; i < (1 << top); i ++){        int cnt = 0, tmp = 1;        for(int j = 0; j < top; j ++){            if(i & (1 << j)){                tmp = tmp * prime[j];                cnt ++;            }        }        if(cnt % 2) ans += C(s / tmp, k);        else ans -= C(s / tmp, k);    }    return ans;}int main(){//    freopen("1.txt", "r", stdin);    int k, s;    while(cin >> k >> s){        int ans = solve(k, s);        if(ans > 10000) ans = 10000;        cout << ans << endl;    }    return 0;}


容斥原理强大。。。学习了。。。 - - 奋斗

0 0
原创粉丝点击