• “蔚来杯“2022牛客暑期多校训练营6 A题: Array


    A题: Array

    原题链接:https://ac.nowcoder.com/acm/contest/33191/A

    题目大意

    给定大小为 n ( 1 ≤ n ≤ 1 0 5 ) n(1\le n\le 10^5) n(1n105) 的数组 a 1 , a 2 , . . . , a n ( 2 ≤ a i ≤ 2 × 1 0 5 ) a_1,a_2,...,a_n(2\le a_i\le 2\times 10^5) a1,a2,...,an(2ai2×105) ,满足 ∑ 1 a i ≤ 1 2 \sum \frac{1}{a_i}\le \frac{1}{2} ai121 。求长度为 m m m 的序列 c 0 , c 1 , . . . , c m − 1 c_0,c_1,...,c_{m-1} c0,c1,...,cm1 。基于序列 c c c ,可以生成无限长的序列 b b b ,满足 b i = c i m o d    m b_i=c_{i \mod m} bi=cimodm b b b 必须满足其中任意连续 a i a_i ai 个数中,必有一个值为 i i i

    注意 a a a 序列下标从 1 1 1 开始, b , c b,c b,c 下标从 0 0 0 开始。 m ∈ [ 1 , 1 0 6 ] m\in [1,10^6] m[1,106] 可以任意选择。

    题解

    充分观察和利用题目条件!
    显然,若 ∑ 1 a i ≤ 1 \sum \frac{1}{a_i}\le 1 ai11 ,则题目是必然有解的。
    题目的条件是 ∑ 1 a i ≤ 1 2 \sum \frac{1}{a_i}\le \frac{1}{2} ai121 ,我们不妨将 a i a_i ai 改为最大的 2 k ≤ a i 2^k\le a_i 2kai (即向下取到最近的 2 2 2 的整数次幂),此时新的 a i ′ > a i 2 a_i'>\frac{a_i}{2} ai>2ai ,即 1 a i ′ < 2 a i \frac{1}{a_i'}<\frac{2}{a_i} ai1<ai2 ,故 ∑ 1 a i ′ < 1 \sum \frac{1}{a_i'}<1 ai1<1 仍有解。
    此时 l c m { a 1 ′ , a 2 ′ , . . . , a n ′ } lcm\{a_1',a_2',...,a_n'\} lcm{a1,a2,...,an} 肯定为一个小于 1 0 6 10^6 106 2 2 2 的整数次幂,我们不妨取 m = 2 19 < 1 0 6 m=2^{19}<10^6 m=219<106
    根据 a i ′ a_i' ai 从小到大,对于每个 i i i 每隔 a i a_i ai 插入一个值,此时因为 m m m a i ′ a_i' ai 的倍数,所以只要序列 c c c 满足要求,由 c c c 的重复周期得到的序列 b b b 也一定满足。
    (注意 a i ′ a_i' ai 要按照从小到大,否则可能出现插入一个 i i i 时,序列 c c c 最前面的一段已经被占满的情况)
    暴力构造即可。

    参考代码

    #include
    using namespace std;
    
    template<class T>inline void read(T&x){
    	char c,last=' ';
    	while(!isdigit(c=getchar()))last=c;
    	x=c^48;
    	while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+(c^48);
    	if(last=='-')x=-x;
    }
    
    #define P pair<int,int> 
    const int MAXN=1e6+5;
    int n;
    int a[MAXN];
    P p[MAXN];
    int ans[MAXN];
    
    int main()
    {
    	read(n);
    	for(int i=1;i<=n;++i){
    		read(a[i]);
    		while(a[i]&(a[i]-1))a[i]-=(a[i]&-a[i]);//(a[i]&(a[i]-1))判断是否为2的整数次幂,(a[i]&-a[i])取出当前二进制中最低的1
    		p[i]=P(a[i],i);
    	}
    	sort(p+1,p+n+1);
    	int lim=1<<19;
    	for(int i=1,j=1;i<=n;++i){
    		while(ans[j])++j;//跳过已经使用的位
    		for(int k=j;k<=lim;k+=p[i].first)ans[k]=p[i].second;
    	}
    	for(int i=1;i<=lim;++i)if(!ans[i])ans[i]=1;//补足空位
    	cout<<lim<<'\n';
    	for(int i=1;i<=lim;++i)cout<<ans[i]<<" \n"[i==lim];
    	return 0;
    }
    
    • 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
  • 相关阅读:
    Nginx可以通过配置文件实现三种常见的负载均衡方式
    PHP简单实现预定义钩子和自定义钩子
    Python - 一个恶意脚本
    深入浅出 JavaScript 模块化
    币圈必备资讯插件
    Java项目源码javaweb花店销售管理系统
    面向对象12:什么是多态
    软件工程复习
    12(第十一章,数据仓库和商务智能)
    怎样学习做自媒体?
  • 原文地址:https://blog.csdn.net/Spy_Savior/article/details/126199879