• 【贪心构造证明】Codeforces Round #814 (Div. 2) E. Fibonacci Strings


    题意:
    给定 k k k 种不同的字符,第 i i i 种字符有 c i c_i ci 种。
    所有字符可以随意顺序放,得到的序列按照相同数分成一段,问最后从前到后的每段数量是否可以构成一个斐波那契数列。
    如: a : 1 , b : 2 , c : 3 a:1,b:2,c:3 a:1,b:2,c:3
    a b c b c c abcbcc abcbcc 对应为: 1 ( a ) , 1 ( b ) , 1 ( c ) , 1 ( b ) , 2 ( c c ) 1(a),1(b),1(c),1(b),2(cc) 1(a),1(b),1(c),1(b),2(cc)
    a b b c c c abbccc abbccc 对应为: 1 ( a ) , 2 ( b b ) , 3 ( c c c ) 1(a),2(bb),3(ccc) 1(a),2(bb),3(ccc)

    如: a : 1 , b : 4 , c : 2 a:1,b:4,c:2 a:1,b:4,c:2
    a b c c b b b abccbbb abccbbb 对应为: 1 ( a ) , 1 ( b ) , 2 ( c ) , 3 ( b b b ) 1(a),1(b),2(c),3(bbb) 1(a),1(b),2(c),3(bbb),这就是一个斐波那契数列
    注意第一个和第二个值都为 1 1 1

    数据范围: 1 ≤ k ≤ 100 , 1 ≤ c i ≤ 1 0 9 1\leq k\leq 100, 1\leq c_i\leq 10^9 1k100,1ci109

    题解:
    首先,易得斐波那契数列的个数是不会很多的,因为每个数最多 1 0 9 10^9 109,所以最大的一项不能超过 1 0 9 10^9 109;其次,因为需要将所有字符都分配出去,因此对应的字符数量和一定是一个斐波那契数列的前缀和。不满足上述的条件必然不能构成。

    之后我们考虑如何去构造这个序列。
    从最大的数开始,首先对应的字符种类的字符数量必须不小于这个最大的数,那么如果有多个,该选择哪个数呢?

    对于最大的数,如果其不选择 f [ i ] f[i] f[i],那么其最多可以选择的和是 f [ i − 1 ] + f [ i − 3 ] + f [ i − 5 ] + . . . f[i-1]+f[i-3]+f[i-5]+... f[i1]+f[i3]+f[i5]+...

    我们考虑如下问题: f [ i ] ≥ f [ i − 1 ] + f [ i − 3 ] + f [ i − 5 ] + . . . f[i]\geq f[i-1]+f[i-3]+f[i-5]+... f[i]f[i1]+f[i3]+f[i5]+...,这里斐波拉契下标从 0 0 0 开始
    这个问题很好证明:

    • i i i 是偶数
      f [ i ] > f [ i − 1 ] + f [ i − 3 ] + . . . + f [ 1 ] f[i] > f[i-1]+f[i-3]+...+f[1] f[i]>f[i1]+f[i3]+...+f[1]
      因为 f [ i ] = f [ i − 1 ] + f [ i − 2 ] f[i]=f[i-1]+f[i-2] f[i]=f[i1]+f[i2]
      f [ i − 2 ] > f [ i − 3 ] + . . . f [ 1 ] f[i-2]>f[i-3]+...f[1] f[i2]>f[i3]+...f[1]
      因为 f [ i − 2 ] = f [ i − 3 ] + f [ i − 4 ] f[i-2]=f[i-3]+f[i-4] f[i2]=f[i3]+f[i4]
      f [ i − 4 ] > f [ i − 5 ] + . . . + f [ 1 ] f[i-4]>f[i-5]+...+f[1] f[i4]>f[i5]+...+f[1]
      如此下去
      最后是: f [ 2 ] > f [ 1 ] f[2]>f[1] f[2]>f[1],这是显然的。
    • i i i 是奇数
      f [ i ] ≥ f [ i − 1 ] + f [ i − 3 ] + . . . + f [ 0 ] f[i]\geq f[i-1]+f[i-3]+...+f[0] f[i]f[i1]+f[i3]+...+f[0]
      同上,最后是 f [ 1 ] ≥ f [ 0 ] f[1]\geq f[0] f[1]f[0],这是显然的。

    综上,如果最大的数 a m a x a_{max} amax 不选择 f [ i ] f[i] f[i],那么他最多只能选择的数不会大于 f [ i ] f[i] f[i],甚至小于 f [ i ] f[i] f[i],那么对于这个最大的数可能会用不完其所有的字符。因此,贪心地每次让最大的数选择即可,如果当前 f [ i ] f[i] f[i] 找不到一个可以覆盖它的字符种类,那么无解。

    代码:

    #include 
    using namespace std;
    
    typedef long long ll;
    
    const int N = 110; 
    map<ll, int> mp;
    ll fib[N];
    ll a[N], n;
    
    void solve() {
    	scanf("%lld", &n);
    	ll sum = 0;
    	for (int i = 1; i <= n; ++i)scanf("%lld", &a[i]), sum += a[i];
    	if (!mp.count(sum)) {
    		puts("NO");
    		return ;
    	} 
    	
    	int last = 0;
    	int st = mp[sum];
    	for (int i = st; i >= 0; --i) {
    		int id = -1;
    		for (int j = 1; j <= n; ++j)
    			if (j != last) if (id == -1 || a[id] < a[j]) id = j;
    		if (id == -1 || a[id] < fib[i]) {
    			puts("NO");
    			return ;
    		}
    		a[id] -= fib[i];
    		last = id;
    	}
    	puts("YES");
    }
    
    int main()
    {
    	fib[0] = fib[1] = 1;
    	mp[1] = 0, mp[2] = 1;
    	ll sum = 2;
    	for (int i = 2; i <= 43; ++i) {
    		fib[i] = fib[i - 1] + fib[i - 2];
    		sum += fib[i];
    		mp[sum] = i;
    	}
    	
    	int T = 1;
    	scanf("%d", &T);
    	for (int i = 1; i <= T; ++i) {
    		solve();
    	}
    	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
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
  • 相关阅读:
    第一个 Shell 脚本
    别再用 System.currentTimeMillis 统计耗时了,太LOW,这个工具类好用到爆!
    SQL基本查询
    腾讯mini项目-【指标监控服务重构】2023-08-24
    SpringCloud微服务实战——搭建企业级开发框架(四十八):【移动开发】整合uni-app搭建移动端快速开发框架-使用第三方UI框架
    Synaptic Systems NeuN抗体的应用和参考文献
    现代电信交换【复习&上课时的习题】
    P1952 火星上的加法运算
    2009-2021系统架构设计师(高级)历年论文题目
    【golang/问题记录】goroutine之间数据竞争问题
  • 原文地址:https://blog.csdn.net/weixin_43900869/article/details/126394113