zoukankan      html  css  js  c++  java
  • HDU. 5334. Virtual Participation(构造)

    题目链接

    网上这题题解都是远古时代的了... 很多不太靠谱。不过dls这课件也是远古-的了(但还加新题好良心)


    (Description)
    给定(K)。构造一个字符集大小没有限制、长度不超过(10^5)的字符串,使得不同的子串个数恰好为(K)
    (Kleq 10^9)

    (Solution)
    做法1:
    考虑简单的(egin{matrix}underbrace{111...1}\a_1个end{matrix}egin{matrix}underbrace{222...2}\a_2个end{matrix}egin{matrix}underbrace{333....}\a_3个..end{matrix})(sum a_i=n),则不同子串数为:(C_{n+1}^2-sum_{a_igeq 2} C_{a_i}^2)
    不妨先求出最小的(n)使得(C_{n+1}^2geq K)
    (x=C_{n+1}^2-K),有一个结论是“任何一个数可由最多三个三角数/三角形数构成”,所以从大到小找出构成(x)(C_{a_i}^2 (a_igeq 2))即可。剩下(L-sum a_i)的数直接补(4 5 6 7 8...)

    网上有个题解是从小到大找,似乎是会超过三个的(不满足结论)。

    细节:(K)较小如(K=4)时(实测只有(K=4)(K=16)),(sum a_i)会大于(n)(因为(C_n^2)增长不够快还是?)。所以(K)较小时需特判,直接输出(K)(1)就ok。

    做法2
    直接考虑构造(egin{matrix}underbrace{111...1}\a个end{matrix}egin{matrix}underbrace{222...2}\b个end{matrix}egin{matrix}underbrace{111...1}\c个end{matrix}),令(ageq c),则子串数为(ab+bc+ac+a+b)
    条件为(ab+bc+ac+a+b=K)((a+c+1)(b+c+1)=K+(c+1)^2),枚举(c+1)(a),保证(ageq c)(a+b+cleq 10^5)即可找到解。
    (K)较大的时候,这个枚举效率似乎就不如做法1了。


    //124MS	1384Kb
    #include <bits/stdc++.h>
    #define pc putchar
    #define pb emplace_back
    typedef long long LL;
    const int N=1e5+5;
    
    int main()
    {
    	int K;
    	while(~scanf("%d",&K))
    	{
    		if(K<=1000)//(K==4||K==16)
    		{
    			printf("%d
    ",K);
    			for(int i=1; i<=K; ++i) printf("%d%c",1," 
    "[i==K]);
    			continue;
    		}
    		int l=1,r=44721,mid;
    		while(l<r)
    			if(mid=l+r>>1,mid*(mid+1)/2>=K) r=mid;
    			else l=mid+1;
    
    		int n=l,x=n*(n+1)/2-K;
    		std::vector<int> vec;
    		while(x)
    		{
    			int l=1,r=sqrt(2*x)+1,mid,ans=1;
    			while(l<=r)
    				if(mid=l+r>>1,mid*(mid-1)/2<=x) ans=mid,l=mid+1;
    				else r=mid-1;
    			vec.pb(ans), x-=ans*(ans-1)/2;
    		}
    		int now=1,f=0; printf("%d
    ",n);
    		for(auto t:vec)
    		{
    			for(int i=1; i<=t; ++i)
    				if(f) printf(" %d",now);
    				else f=1, printf("%d",now);
    			++now, n-=t;
    		}
    		while(n--)
    			if(f) printf(" %d",now++);
    			else f=1, printf("%d",now++);
    		pc('
    ');
    	}
    
    	return 0;
    }
    
    ------------------------------------------------------------------------------------------------------------------------
    无心插柳柳成荫才是美丽
    有哪种美好会来自于刻意
    这一生波澜壮阔或是不惊都没问题
    只愿你能够拥抱那种美丽
    ------------------------------------------------------------------------------------------------------------------------
  • 相关阅读:
    一款开源免费跨浏览器的视频播放器--videojs使用介绍(转)
    forward内部跳转 和redirect重定向跳转的区别
    心理学--斯纳金
    心理学--大脑
    心理学--普及
    经济--国债,外汇
    经济--公积金
    经济--技术分析
    经济--分级基金3
    经济--分级基金
  • 原文地址:https://www.cnblogs.com/SovietPower/p/14432574.html
Copyright © 2011-2022 走看看