UVa 1635 - Irrelevant Elements(二项式系数 + 唯一分解定理)

链接:

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4510

 

题意:

对于给定的n个数a1, a2,…, an,依次求出相邻两数之和,将得到一个新数列。重复上述操作,最后结果将变成一个数。
问这个数除以m的余数与哪些数无关?例如n=3,m=2时,第一次求和得到a1+a2,a2+a3,
再求和得到a1+2a2+a3,它除以2的余数和a2无关。1≤n≤1e5,2≤m≤1e9。

 

分析:

不难证明,在一般情况下,最后ai的系数是C(n-1,i-1)。这样,问题就变成了求C(n-1,0), C(n-1,1), ...,C(n-1,n-1)中
有哪些是m的倍数。理论上,利用C(n,k) = (n-k+1)/k * C(n,k-1)可以递推出所有C(n-1,i-1),但它们太大了,
虽然可以用高精度,但是运算会很慢。然而此问题中所关心的只是“哪些是m的倍数”,所以只需要依次计算m的
唯一分解式中各个素因子在C(n-1,i-1)中的指数即可完成判断。这些指数仍然可以用上式递推,并且不会涉及高精度。

 

代码:

 1 import java.io.*;
 2 import java.util.*;
 3 
 4 public class Main {
 5     static ArrayList<Integer> prime = new ArrayList<Integer>();
 6     
 7     static void resolve(int m) {
 8         int u = (int)Math.sqrt(m + 0.5);
 9         for(int i = 2; i <= u; i++) {
10             if(m % i != 0) continue;
11             prime.add(i);
12             while(m % i == 0) m /= i;
13         }
14         if(m > 1) prime.add(m);
15     }
16     
17     public static void main(String args[]) {
18         Scanner cin = new Scanner(new BufferedInputStream(System.in));
19         
20         while(cin.hasNext()) {
21             int n = cin.nextInt();
22             int m = cin.nextInt();
23             
24             n--;
25             boolean bad[] = new boolean[n+5];
26             prime.clear();
27             resolve(m);
28             for(int t = 0; t < prime.size(); t++) { // 求C(n,0)~C(n,n)有哪些数是m的倍数
29                 int p = prime.get(t), e = 0, x = m, min = 0; // C(n,i) = p^e
30                 while(x % p == 0) { x /= p;  min++; }
31                 for(int k = 1; k < n; k++) { // C(n,k)=C(n,k-1)*(n-k+1)/k
32                     x = n - k + 1;
33                     while(x % p == 0) { x /= p;  e++; }
34                     x = k;
35                     while(x % p == 0) { x /= p;  e--; }
36                     if(e < min) bad[k] = true;
37                 }
38             }
39             
40             ArrayList<Integer> ans = new ArrayList<Integer>();
41             for(int i = 1; i < n; i++) if(!bad[i]) ans.add(i+1);
42             System.out.println(ans.size());
43             if(ans.size() > 0) {
44                 System.out.print(ans.get(0));
45                 for(int i = 1; i < ans.size(); i++)
46                     System.out.print(" " + ans.get(i));
47             }
48             System.out.println();
49         }
50         cin.close();
51     }
52 }

 

posted @ 2018-04-21 21:27  Ctfes  阅读(173)  评论(0编辑  收藏  举报