细胞分裂【唯一分解定理】

题目链接:https://ac.nowcoder.com/acm/contest/1106/B

题目大意:

1.依次给出n,m1,m2,si。m1的m2次方代表一个值A,求在n个si中,各个si的x次方是A的倍数,x的最小值。

题解思路:

1.对m1进行质因数分解,得到每个质因子的次方,次方乘个m2即得到m1^m2的质因数分解结果。

2.枚举si,对于每一个si,若其没有包含m1^m2所有的质因数,则任si次方增长也无法达到m1^m2的倍数。若包含了m1^m2的所有质因数,则只需要求这些质因数 在m1^m2中的次方比上在si中的次方,向上取整,取其中的最大值。(意为si达到m1 ^m2的倍数至少需要增加的次方数)。结果是对于每一个si的结果取最小值。

代码如下:

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<math.h>
 4 #include<algorithm>
 5 #define mem(a, b) memset(a, b, sizeof(a))
 6 const int inf = 0x3f3f3f3f;
 7 using namespace std;
 8 
 9 int n, m1, m2, cnt;
10 int s[10010], vis[30010], a[30010], b[30010]; //a存质因子,b存该质因子的次数 
11 int prime[30010];
12 
13 void get_prime(int n)  //得到2~m1范围内所有的素数 
14 {
15     mem(vis, 1), cnt = 0;
16     for(int i = 2; i <= n; i ++)
17     {
18         if(vis[i])
19         {
20             prime[++ cnt] = i;
21             for(int j = i; j <= n; j += i)
22                 vis[j] = 0;
23         }
24     }
25 }
26 
27 int main()
28 {
29     int n;
30     scanf("%d%d%d", &n, &m1, &m2);
31     for(int i = 1; i <= n; i ++)
32         scanf("%d", &s[i]);
33     if(m1 == 1)
34         printf("0\n");
35     else
36     {
37         get_prime(m1);
38         int x = m1, k = 0; //k是质因子数量 
39         for(int i = 1; i <= cnt; i ++)
40         {
41             if(x % prime[i] == 0)
42             {
43                 k ++;
44                 a[k] = prime[i];
45                 int p = 0;  //该质因子次数 
46                 while(x % prime[i] == 0)
47                 {
48                     p ++;
49                     x /= prime[i];
50                 }
51                 b[k] = p * m2;  //得到m1 ^ m2的所有质因数以及次方 
52             }
53             if(x == 1)
54                 break;
55         }
56         int ans = inf;
57         for(int i = 1; i <= n; i ++)
58         {
59             int maxx = 0;
60             for(int j = 1; j <= k; j ++)
61             {
62                 if(s[i] % a[j]) //若s[i]没有包含m1 ^ m2的所有质因数,则去除掉 
63                 {
64                     maxx = inf;
65                     break;
66                 }
67                 int p = 0, x = s[i];
68                 while(x % a[j] == 0)
69                 {
70                     x /= a[j];
71                     p ++;
72                 }
73                 int temp = ceil(b[j] * 1.0 / p); //注意向上取整时,转化成浮点型计算,否则整形/整形依然是整形,没有达到向上取整的作用 
74                 maxx = max(maxx, temp);
75             }
76             ans = min(ans, maxx);
77         }
78         if(ans == inf)
79             printf("-1\n");
80         else
81             printf("%d\n", ans);
82     }
83     return 0;
84 }
View Code

扩展:

该解法用于,求解一个数B的最小次方x是A的倍数,求x。(当A是m1^m2型很大的数据时,B的次方也很大时)。

猜你喜欢

转载自www.cnblogs.com/yuanweidao/p/11748906.html
今日推荐