洛谷P1069 细胞分裂

洛谷 P1069 [NOIP2009 普及组] 细胞分裂

题目描述

HanksHanks 博士是 BTB**T (Bio-TechBioTec**h,生物技术) 领域的知名专家。现在,他正在为一个细胞实验做准备工作:培养细胞样本。

HanksHanks 博士手里现在有 NN种细胞,编号从 1-N1−N,一个第 ii种细胞经过 11 秒钟可以分裂为S_iS**i个同种细胞(S_iS**i为正整数)。现在他需要选取某种细胞的一个放进培养皿,让其自由分裂,进行培养。一段时间以后,再把培养皿中的所有细胞平均分入MM个试管,形成MM份样本,用于实验。HanksHanks 博士的试管数MM很大,普通的计算机的基本数据类型无法存储这样大的MM值,但万幸的是,MM 总可以表示为m_1m1的m_2m2次方,即M = m_1^{m_2}M=m1m2,其中 m_1,m_2m1,m2均为基本数据类型可以存储的正整数。

注意,整个实验过程中不允许分割单个细胞,比如某个时刻若培养皿中有 44个细胞,

HanksHanks博士可以把它们分入 22 个试管,每试管内22 个,然后开始实验。但如果培养皿中有55个细胞,博士就无法将它们均分入22 个试管。此时,博士就只能等待一段时间,让细胞们继续分裂,使得其个数可以均分,或是干脆改换另一种细胞培养。

为了能让实验尽早开始,HanksHanks博士在选定一种细胞开始培养后,总是在得到的细胞“刚好可以平均分入 MM个试管”时停止细胞培养并开始实验。现在博士希望知道,选择哪种细胞培养,可以使得实验的开始时间最早。

输入格式

第一行,有一个正整数 NN,代表细胞种数。

第二行,有两个正整数 m_1,m_2m1,m2,以一个空格隔开,即表示试管的总数 M = m_1^{m_2}M=m1m2.

第三行有 N 个正整数,第 i 个数 Si表示第 i 种细胞经过 1 秒钟可以分裂成同种细胞的个数。

输出格式

一个整数,表示从开始培养细胞到实验能够开始所经过的最少时间(单位为秒)。

如果无论HanksHanks博士选择哪种细胞都不能满足要求,则输出整数-1−1。

输入输出样例

输入 #1复制

1
2
3
1 
2 1
3

输出 #1复制

1
-1

输入 #2复制

1
2
3
2
24 1
30 12

输出 #2复制

1
2

说明/提示

【输入输出说明】

经过 11秒钟,细胞分裂成33 个,经过22秒钟,细胞分裂成99个,……,可以看出无论怎么分裂,细胞的个数都是奇数,因此永远不能分入 22个试管。

【输入输出样例22说明】

第 11 种细胞最早在33 秒后才能均分入2424 个试管,而第22 种最早在22 秒后就可以均分(每试管144/(241)=6144/(241)=6 个)。故实验最早可以在22 秒后开始。

【数据范围】

对于 50%的数据,有m_1^{m_2} ≤ 30000m1m2≤30000。

对于所有的数据,有1 ≤N≤ 10000,1 ≤m_1 ≤ 30000,1 ≤m_2 ≤ 10000,1 ≤ S_i ≤ 2,000,000,0001≤N≤10000,1≤m1≤30000,1≤m2≤10000,1≤S**i≤2,000,000,000。

NOIP 2009 普及组 第三题


分析

纯纯的数论题,但是以我的水平根本就别想做出来。

看这篇题解做的https://www.luogu.com.cn/blog/xcg--123/solution-p1069

高中养成的坏习惯,看到难题总是懒得思考直接小猿搜题,导致现在思考的能力很差,完全没有思维的逻辑,推理的能力也很差,导致现在做这种数学题非常吃力。


代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include <iostream>
#include <algorithm>
using namespace std;

int gcd(int a, int b);
int N, m1, m2;
int S[10010];
int minX = 0x7fffffff, ans = 0x7fffffff;

int main(int argc, const char *argv[])
{
cin >> N >> m1 >> m2;
if(m1 == 1)
{
cout << 0 << endl;
return 0;
}
for(int i = 0; i < N; i++)
cin >> S[i];
for(int i = 0; i < N; i++)
{
int m = m1, s = S[i], q = 0;
int temp = 0x7fffffff;
bool flag = true;
int t = 0;
while(m != 1)
{
int gcdd = gcd(m, s);
if(gcdd == 1)
{
flag = false;
break;
}
m /= gcdd;
q = s / gcdd;
s = gcdd;
t++;
}
if(flag)
{
int gc = gcd(q, s);
if(gc != 1 && gc != s)
{
int totq = 0, tots = 0;
while(q % gc == 0)
{
totq++;
q /= gc;
}
while(s % gc == 0)
{
tots++;
s /= gc;
}
if((t * m2 * tots + totq * (t - 1) * m2) % (tots + totq) == 0)
temp = (t * m2 * tots + totq * (t - 1) * m2) / (tots + totq);
else
temp = (t * m2 * tots + totq * (t - 1) * m2) / (tots + totq) + 1;
ans = min(temp, ans);
}
else
{
int tot = 0;
while(q % s == 0)
{
tot++;
q /= s;
}
if((t * m2 + tot * (t - 1) * m2) % (tot + 1) == 0)
temp = (t * m2 + tot * (t - 1) * m2) / (tot + 1);
else
temp = (t * m2 + tot * (t - 1) * m2) / (tot + 1) + 1;
ans = min(temp, ans);
}
}
}
if(ans == 0x7fffffff)
cout << -1 << endl;
else
cout << ans << endl;

return 0;
}


int gcd(int a, int b)
{
if(b == 0)
return a;
else
return gcd(b, a % b);
}
作者

Jhuoer Yen

发布于

2021-05-28

更新于

2023-09-18

许可协议

评论

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×