• arc106E


    题目大意

    有n个人,第i个人有一个ai,表示其第[k(2ai)+1,k(2ai)+ai]天在

    每天可以给至多一个人发一枚奖牌,求所有人都发了只少K枚奖牌的最小时间

    n<=18,K,ai<=1e5

    题解

    如果能想到hall定理的话就没了

    一个人拆成K个点,二分答案,暴力加边,hall定理判断,要预处理选牌的人的集合

    code

    #include <bits/stdc++.h>
    #define fo(a,b,c) for (a=b; a<=c; a++)
    #define fd(a,b,c) for (a=b; a>=c; a--)
    #define low(x) ((x)&-(x))
    #define ll long long
    //#define file
    using namespace std;
    
    int a[19],b[4000001],f[262144],p[19],num[262144],n,K,i,j,k,l,L,R,Mid;
    
    void init()
    {
    	int s,i,j,k,l;
    	p[0]=1;
    	fo(i,1,n) p[i]=p[i-1]*2;
    	fo(i,1,p[n]-1) num[i]=num[i-low(i)]+1;
    	
    	fo(i,1,4000000)
    	{
    		s=0;
    		fo(j,1,n)
    		if ((i-1)%(a[j]*2)<a[j])
    		s+=p[j-1];
    		b[i]=s;
    	}
    }
    bool pd(int t)
    {
    	int i,j,k,l,s;
    	
    	memset(f,0,sizeof(f));
    	fo(i,1,t) ++f[p[n]-1],--f[b[i]^(p[n]-1)];
    	fo(i,1,n)
    	{
    		fo(j,0,p[n]-1)
    		if (j&p[i-1])
    		f[j-p[i-1]]+=f[j];
    	}
    	
    	fo(i,0,p[n]-1)
    	if (num[i]*K>f[i])
    	return 0;
    	return 1;
    }
    
    int main()
    {
    	#ifdef file
    	freopen("e.in","r",stdin);
    	#endif
    	
    	scanf("%d%d",&n,&K);
    	fo(i,1,n) scanf("%d",&a[i]);
    	init();
    	
    	L=1,R=4000000;
    	while (L<R)
    	{
    		Mid=(L+R)/2;
    		if (!pd(Mid))
    		L=Mid+1; else R=Mid;
    	}
    	printf("%d
    ",L);
    	
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    jQuery仿yahoo首页弹出层效果
    显示中文的星期几
    Oracle 會話級Session誤解
    异常处理點滴
    DataGrid 呈現數據——綁定與編程混合
    document.body.scrollTop 值总为0的解决方法(转载)
    DataGridView 一些設置
    事務回滾之實例
    数据库表设计下手
    WebApp匯入CSV資料
  • 原文地址:https://www.cnblogs.com/gmh77/p/13873708.html
Copyright © 2020-2023  润新知