• Codeforces Round #724 (Div. 2)


    D. Omkar and Medians

    题目描述

    点此看题

    解法

    不难想到可以保证 (b[1...i-1]) 这些中位数合法,考虑加入两个数让 (b[i]) 也合法,可以用的条件是 (b[i-1]) 是前 (2i-3) 个数的中位数,可以讨论 (b[i])(b[i-1]) 的关系:

    • 如果 (b[i]>b[i-1]),那么此时一定有 (i-1) 个数比 (b[i]) 小,所以 (b[i])(b[i-1]) 中间就不能有任何元素。
    • 如果 (b[i]<b[i-1]),那么此时一定有 (i-1) 个数比 (b[i]) 大,所以 (b[i])(b[i-1]) 中间就不能有任何元素。
    • 如果 (b[i]=b[i-1]) 显然仍然可以合法。

    如果满足上述条件那么一定有解,我们把随意确定的元素放在正无穷或者负无穷即可,我们可以用 ( t set) 来判断前驱后继,或者利用前驱后继的特性可以直接用双向链表 (O(n)) 解决。

    #include <cstdio>
    #include <set>
    using namespace std;
    const int M = 200005; 
    int read()
    {
    	int x=0,f=1;char c;
    	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
    	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
    	return x*f;
    }
    int T,n,f,a[M];set<int> s;
    signed main()
    {
    	T=read();
    	while(T--)
    	{
    		n=read();s.clear();f=1;
    		for(int i=1;i<=n;i++)
    		{
    			a[i]=read();
    			s.insert(a[i]);
    			if(i==1 || a[i]==a[i-1]) continue;
    			if(a[i]>a[i-1] && *s.upper_bound(a[i-1])!=a[i])
    				f=0;
    			if(a[i]<a[i-1] && *s.upper_bound(a[i])!=a[i-1])
    				f=0;
    		}
    		if(f) puts("YES");
    		else puts("NO");
    	}
    }
    

    E. Omkar and Forest

    题目描述

    点此看题

    解法

    这道题有两个限制,不妨一起用:如果当前格子为 (x>0),那么存在一个相邻的格子满足其权值恰好为 (x-1)

    这就是 ( t bfs) 的过程嘛!所以如果固定了 (0),那么剩下的权值也就确定了,设#的数量是 (cnt),那么方案数就是 (2^{cnt}),如果整张图都是#那么答案是要减 (1),因为要排除全部非 (0) 的情况。

    #include <cstdio>
    const int M = 2005;
    const int MOD = 1e9+7;
    int read()
    {
    	int x=0,f=1;char c;
    	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
    	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
    	return x*f;
    }
    int T,n,m,f,ans;char s[M];
    signed main()
    {
    	T=read();
    	while(T--)
    	{
    		n=read();m=read();f=ans=1;
    		for(int i=1;i<=n;i++)
    		{
    			scanf("%s",s+1);
    			for(int j=1;j<=m;j++)
    			{
    				if(s[j]=='0') f=0;
    				else ans=ans*2%MOD;
    			}
    		}
    		printf("%d
    ",ans-f);
    	}
    }
    

    F. Omkar and Akmar

    题目描述

    点此看题

    解法

    首先考虑必胜策略,终止状态要不然是-A-B-,要不然是-A-X-B,也就是说空格一定夹在AB之间的。考虑去掉空格后是AB交替出现的一个环,所以AB的出现次数都是偶数,推出后手必胜,而且无论怎么玩都是后手必胜。

    那么把操作序列的个数算出来就行了,假设最后有 (k) 个空格,那么就有 ((n-k)!) 种操作方法,再乘上在长度为 (n) 的环中选取 (k) 个空格不能相邻的方案数即可,这时候我们要破环为链,设 (f(n,k)) 为长度为 (n) 的序列中选 (k) 个空格不能相邻的方案数,讨论第一个格子是不是空格,方案数是 (f(n-1,k)+f(n-3,k-1))

    (f) 的计算是容易的,我们先拿出 (k-1) 个格子,再从中任意选取 (k) 个空格,方案数是 ({n-k+1choose k})

    因为ABABBABA都是可以的,所以答案需要乘 (2)

    #include <cstdio>
    const int MOD = 1e9+7;
    const int M = 1000005; 
    #define int long long 
    int read()
    {
    	int x=0,f=1;char c;
    	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
    	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
    	return x*f;
    }
    int n,ans,fac[M],inv[M];
    void init(int n)
    {
    	fac[0]=inv[0]=inv[1]=1;
    	for(int i=2;i<=n;i++) inv[i]=inv[MOD%i]*(MOD-MOD/i)%MOD;
    	for(int i=1;i<=n;i++) inv[i]=inv[i-1]*inv[i]%MOD;
    	for(int i=1;i<=n;i++) fac[i]=fac[i-1]*i%MOD;
    }
    int C(int n,int m)
    {
    	if(n<m || m<0) return 0;
    	return fac[n]*inv[m]%MOD*inv[n-m]%MOD;
    }
    int f(int n,int k)
    {
    	return C(n-k+1,k);
    }
    signed main()
    {
    	n=read();init(n+1);
    	for(int i=0;i<=n;i++)
    	{
    		if((n-i)&1) continue;
    		int t=(f(n-1,i)+f(n-3,i-1))%MOD;
    		ans=(ans+2*fac[n-i]*t)%MOD;
    	}
    	printf("%lld
    ",ans);
    }
    
  • 相关阅读:
    title()、upper()、lower()的用法
    Oracle用户无法访问ASM磁盘组问题
    Oracle-RAC监听服务进程关闭失败问题分析处理
    SHELL-字符串操作和变量替换
    Linux-按文件大小排序
    MySQL-重置root密码问题
    Oracle-表空间添加数据文件扩容出错解决措施
    Logstash-使用
    Logstash-工作原理
    ELK+filebeat+kafka搭建Oracle数据库日志平台
  • 原文地址:https://www.cnblogs.com/C202044zxy/p/14878876.html
Copyright © 2020-2023  润新知