Original question: Ural 1091 http://acm.timus.ru/problem.aspx? Space = 1 & num = 1091
Ask for k different numbers so that they have an appointment greater than 1, and all numbers cannot be greater than a specified number S.
Solution: You can consider the prime number in each second. This prime number and all its multiples constitute a set, then you can go to any k elements in these sets, C (n, k) that is, the number of methods in this case, such as K = 3, S = 10,
Three sets can be formed: {2, 4, 6, 8, 10}, {3, 6, 9}, {5, 10}, the first set C (5, 3 ), the second set C (3, 3), and the third set is 0. At the same time, we can see that 6 appears in both sets, so we need to subtract a 6, this is the principle of rejection.
Enumerate one prime number and two prime numbers, because if the three prime numbers are at least 2x3x5 = 30, in this case, there is only one (S <= 50) multiple of 30 in s, that is, 30 itself. It is impossible to select K> = 2. Therefore, three or more items are excluded.
Code:
#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#define ll long longusing namespace std;#define N 10007ll C[55][55];int prime[10] = {2,3,5,7,11,13,17,19,23};void calc_C(){ memset(C,0,sizeof(C)); C[1][0] = C[1][1] = 1; for(int i=2;i<=51;i++) { C[i][0] = 1; for(int j=1;j<=51;j++) C[i][j] = C[i-1][j] + C[i-1][j-1]; }}int main(){ int k,S,i,j,res,num,flag; calc_C(); while(scanf("%d%d",&k,&S)!=EOF) { ll res = 0; flag = 9; for(i=0;i<9;i++) { num = S/prime[i]; if(num < k) { flag = i; break; } else res += C[num][k]; } for(i=0;i<flag;i++) { for(j=i+1;j<flag;j++) { num = S/(prime[i]*prime[j]); if(num < k) break; else res -= C[num][k]; } } printf("%lld\n",min((ll)10000,res)); } return 0;}
View code