zoukankan      html  css  js  c++  java
  • 【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;
    }
    
  • 相关阅读:
    Python服务Dokcer化并k8s部署实例
    Docker Machine
    Docker使用Portainer搭建可视化界面
    三小时攻克 Kubernetes!
    Docker使用pipework配置本地网络
    使用kubeadm安装kubernetes1.12.2版本脚本【h】
    rsync详解之exclude排除文件(转)
    linux生成指定大小的文件(转)
    chown将指定文件的拥有者改为指定的用户或组(转)
    Linux系统分析命令总结
  • 原文地址:https://www.cnblogs.com/stoorz/p/15419120.html
Copyright © 2011-2022 走看看