UVa 1635 (唯一分解定理) Irrelevant Elements

经过紫书的分析,已经将问题转化为求组合数C(n-1, 0)~C(n-1, n-1)中能够被m整除的个数,并输出编号(这n个数的编号从1开始)

首先将m分解质因数,然后记录下每个质因子对应的指数。

由组合恒等式,我们可以递推C(n, k)的质因数的个数。

 

一个没什么用的小优化:因为杨辉三角每一行都是对称的,所以我们可以求出前一半答案,然后根据对称性求出后一半的答案。

需要注意的是,如果答案中有类似C(10, 5)的数,就不要再对称了,会重复的。

这个优化貌似也只能优化0.05s左右。

 

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cmath>
 4 
 5 const int maxn = 100000 + 10;
 6 int prime[maxn], bad[maxn], e[maxn], ans[maxn];
 7 int p_cnt;
 8 
 9 void prime_factors(int n)
10 {
11     p_cnt = 0;
12     int m = floor(sqrt(n) + 0.5);
13     for(int i = 2; i <= m; ++i)
14     {
15         if(n % i == 0)        { prime[p_cnt++] = i; }
16         while(n % i ==0)    { e[p_cnt-1]++; n /= i; }
17     }
18     if(n > 1)
19     {
20         prime[p_cnt] = n;
21         e[p_cnt++] = 1;
22     }
23 }
24 
25 int main()
26 {
27     int n, m;
28     while(scanf("%d%d", &n, &m) == 2)
29     {
30         memset(prime, 0, sizeof(prime));
31         memset(bad, 0, sizeof(bad));
32         memset(ans, 0, sizeof(ans));
33         memset(e, 0, sizeof(e));
34         n--;
35 
36         prime_factors(m);
37         for(int i = 0; i < p_cnt; ++i)
38         {
39             int p = prime[i];
40             int need = e[i];
41             int cur_e = 0;
42             for(int k = 1; k <= n/2; ++k)
43             {
44                 int x = n - k + 1;
45                 while(x % p == 0) { cur_e++; x /= p; }
46                 x = k;
47                 while(x % p == 0) { cur_e--; x /= p; }
48                 if(cur_e < need) bad[k] = 1;
49             }
50         }
51 
52         int ans_cnt = 0;
53         for(int k = 1; k <= n/2; ++k)
54             if(!bad[k]) ans[ans_cnt++] = k;
55         if(ans_cnt)
56         {
57             int p = ans_cnt-1;
58             if(ans[p] * 2 == n) p--;
59             for(int i = p; i >= 0; i--)
60                     ans[ans_cnt++] = n - ans[i];
61             printf("%d\n", ans_cnt);
62             printf("%d", ans[0] + 1);
63             for(int i = 1; i < ans_cnt; ++i) printf(" %d", ans[i] + 1);
64         }
65         else puts("0");
66         printf("\n");
67     }
68 
69     return 0;
70 }
代码君

 

posted @ 2014-12-15 19:16  AOQNRMGYXLMV  阅读(905)  评论(0编辑  收藏  举报