文章目录
- P1069 [NOIP2009 普及组] 细胞分裂
- P1280 尼克的任务
P1069 [NOIP2009 普及组] 细胞分裂
#include
#include
#include
using namespace std ;
int n ;//细胞种类数
int m1 ,m2 ;//底数,指数
int si ;//本细胞1秒能分裂的个数
bool prime[30005] ;//记录是否是质数
int n_prime = 0 ;//质数个数
int p_queue[30005] ;//记录所有质数
void init_prime(int num){//欧拉筛法
for(int i = 2;i <= num;++i)
prime[i] = true ;
for(int i = 2;i <= num;++i){
if(prime[i]){
n_prime++ ;
p_queue[n_prime] = i ;
}
for(int j = 1;j <= n_prime && i * p_queue[j] <= num;++j){
prime[i * p_queue[j]] = false ;
if(i % p_queue[j] == 0) //如果i是合数
break ;
}
}
return ;
}
int timee[30004] ;//记录m1^m2的质因数个数
void get_si_prime(int s){//分解质因数
for(int i = 1;i <= n_prime && s != 1;++i){
while(s % p_queue[i] == 0){
s /= p_queue[i] ;
timee[p_queue[i]]++ ;
}
}
return ;
}
int m1_time[30005] ;
int ans = 30050 ;//答案
int main(){
//初始化,求出前30000内质数
init_prime(30000) ;
//输入
scanf("%d" , &n) ;
scanf("%d%d" , &m1 , &m2) ;
//分解m1的质因数
for(int i = 1;i <= n_prime && m1 != 1;++i){
while(m1 % p_queue[i] == 0){
m1 /= p_queue[i] ;
m1_time[p_queue[i]]++ ;
}
}
for(int i = 1;i <= 30000;++i)
m1_time[i] *= m2 ;//计算每个因数数量
for(int i = 1;i <= n;++i){
//清空timee
for(int j = 1;j <= 30000;++j)
timee[j] = 0 ;
scanf("%d" , &si) ;
//分解si的质因数
get_si_prime(si) ;
//判断是否有m1的因数si没有的
//如果有就跳过
bool flag = false ;
int maxx = 0 ;
for(int j = 1;j <= 30000;++j){
if(m1_time[j] == 0)
continue ;
if(m1_time[j] > 0 && timee[j] == 0){
flag = true ;
break ;
}
if(m1_time[j] <= timee[j])
continue ;
int level = 1 ;
int a = m1_time[j] ;
int b = timee[j] ;
while(a > b * level){
level++ ;
}
if(level == 1)
level = 0 ;
maxx = max(maxx , level) ;
}
if(flag)
continue ;
ans = min(ans , maxx) ;
}
//输出
if(ans == 30050)
printf("-1") ;
else
printf("%d" , ans) ;
return 0 ;
}
P1280 尼克的任务
#include
#include
#include
#include
using namespace std ;
int n ,k ;
int sum[10005] ,num = 1 ,f[10005] ;
struct minute{
int start ,end ;
}tim[10001] ;//每个任务的起始时间和结束时间
bool cmp(minute a , minute b){
//由于是倒着搜,所以一定要将起始时间晚的放到前面
return a.start > b.start ;
}
int main(){
//输入
scanf("%d%d" , &n , &k) ;
for(int i = 1;i <= k;++i){
scanf("%d%d" , &tim[i].start , &tim[i].end) ;
sum[tim[i].start]++ ;//将每个时间的任务个数累加
}
sort(tim+1 , tim+1+k , cmp) ;//排序
for(int i = n;i >= 1;--i){
if(sum[i] == 0)//当前没有任务
f[i] = f[i+1] + 1 ;//倒着搜,空闲时间多1个单位
else//当前有任务
for(int j = 1;j <= sum[i];++j){//遍历所有任务
if(f[i+tim[num].end] > f[i])
//当有到任务结束时空闲时间比现在多的时候
f[i] = f[i+tim[num].end] ;//就做这项任务了
num++ ;//任务号码加1
}
}
printf("%d" , f[1]) ;//答案
return 0 ;
}