• 【CF1586F】Defender of Childhood Dreams


    题目

    题目链接:https://codeforces.com/contest/1586/problem/F
    一张 (n) 个点的竞赛图,所有边都是从编号小的点连向编号大的点。
    如果需要给每条边染上色,求最少需要多少种颜色,使得存在一种染色方法,不存在长度为 (k) 的路径都是同一种颜色。
    (k<nleq 1000)

    思路

    首先考虑怎么挑出若干条边染上第一种颜色。
    (n) 个点分为 (k) 个连续段,每一段大小均为 (lfloorfrac{n}{k} floor)(lfloorfrac{n}{k} floor+1)。然后对于在两个不同段的点,把他们之间的边设为第一种颜色。
    这样从任意点开始,最多只能走 (k-1) 条颜色为 (1) 的路。
    而对于每一个段,都是原问题的一个子问题。直接递归处理,这样最后使用的颜色数是 (lceillog_k n ceil) 的。
    具体实现方面,可以把 (0sim n-1) 的所有数都转化为 (k) 进制,然后对于一条边 (x,y),判断 (x-1)(y-1)(k) 进制下最高是哪一位不同,染上那一位的颜色即可。
    注意是 (0sim n-1),我考场写成了 (1sim n) 然后挂掉了。
    时间复杂度 (O(n^2log n))

    代码

    #include <bits/stdc++.h>
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    using namespace std;
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    
    const int N=1010,LG=12;
    int n,m,lim,a[N][LG+1],pw[LG+1];
    
    int main()
    {
    	scanf("%d%d",&n,&m);
    	pw[0]=1;
    	for (;pw[lim]<n;lim++) pw[lim+1]=pw[lim]*m;
    	for (int i=0;i<n;i++)
    		for (int j=0;j<=lim;j++)
    			a[i][j]=(i/pw[j])%m;
    	for (int i=0;i<=lim;i++)
    		if (n<=pw[i]) { cout<<i<<"
    "; break; }
    	for (int i=0;i<n;i++)
    		for (int j=i+1;j<n;j++)
    			for (int k=lim;k>=0;k--)
    				if (a[j][k]>a[i][k]) { cout<<k+1<<" "; break; }
    	return 0;
    }
    
  • 相关阅读:
    js小数点失精算法修正
    ActiveX控件之ActiveXObject is not defined
    js通过日期计算属于星期几
    标准日期格式化
    js阿拉伯数字转中文大写
    RPC 原理的前生今世
    大型网站架构系列:20本技术书籍推荐
    Zookeeper核心机制
    建造者模式
    模板方法模式
  • 原文地址:https://www.cnblogs.com/stoorz/p/15419120.html
Copyright © 2020-2023  润新知