Ural 1091 Tmutarakan Exams 解题报告(容斥原理)
2014-03-08 16:02
477 查看
1091. Tmutarakan Exams
Time limit: 1.0 secondMemory limit: 64 MB
University of New Tmutarakan trains the first-class specialists in mental arithmetic. To enter the University you should master arithmetic perfectly. One of the entrance exams at the Divisibility Department
is the following. Examinees are asked to find K different numbers that have a common divisor greater than 1. All numbers in each set should not exceed a given number S. The numbers K andS are announced at the beginning of
the exam. To exclude copying (the Department is the most prestigious in the town!) each set of numbers is credited only once (to the person who submitted it first).
Last year these numbers were K=25 and S=49 and, unfortunately, nobody passed the exam. Moreover, it was proved later by the best minds of the Department that there do not exist sets
of numbers with the required properties. To avoid embarrassment this year, the dean asked for your help. You should find the number of sets of K different numbers, each of the numbers not exceeding S, which have a common divisor greater than
1. Of course, the number of such sets equals the maximal possible number of new students of the Department.
Input
The input contains numbers K and S (2 ≤ K ≤ S ≤ 50).Output
You should output the maximal possible number of the Department's new students if this number does not exceed 10000 which is the maximal capacity of the Department, otherwise you should output 10000.Sample
input | output |
---|---|
3 10 | 11 |
简单分析,假设K=3,如果因子为2,那么共有C(S/2, 3)种情况。因子为3,那么共有C(S/3, 3)种情况。
但是计算3时,6,12,18也计算进去了,而计算2时这三个数也被计算进去了。所有要减去C(S/6, 3)。
依次进行容斥即可。代码如下:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 51; int c[maxn][maxn]; int deg[maxn], cnt[maxn]; int good[maxn]; void calC() { for(int i=0;i<maxn;i++) { c[i][0] = 1; for(int j=1;j<=i;j++) { c[i][j]=c[i-1][j]+c[i-1][j-1]; } } } int co_prime(int s, int k) { memset(deg, 0, sizeof(deg)); memset(cnt, 0, sizeof(cnt)); memset(good, 1, sizeof(good)); int ans = 0; for(int i=2;i<=s;i++) { if(good[i]) { if(deg[i]==0) deg[i]=1; if(s/i<k) break; int add = c[s/i][k]*(deg[i]&1?1:-1); ans += add; for(int j=2;i*j<=s;j++) { if(deg[i]==1) if(j%i==0) good[i*j]=false; else deg[i*j]++; } } } return ans<=10000?ans:10000; } int main() { calC(); int k,s; while(~scanf("%d%d",&k,&s)) { printf("%d\n", co_prime(s, k)); } }
相关文章推荐
- 1.m分解阶乘之和
- 2.几种递推数
- 3.欧拉函数
- 4.快速幂模m算法
- 5.扩展欧几里得&&中国剩余定理
- 6.数论_web
- Codeforces Round #198 (Div. 1)
- 组合数求模总结
- 【数论学习】数论分析证明
- 整数对
- Leftmost Digit
- POJ 3292.Semi-prime H-numbers
- ZOJ 3547 《The Boss on Mars》(容斥定理)
- HDU 1133 (数论 or DP、高精度;Java版)
- POJ 1061 青蛙的约会
- zoj_3621 Factorial Problem in Base K
- zoj_1657 Goldbach's Conjecture
- zoj_1526 Big Number
- poj_3210 Coins
- poj_1528 Perfection