[CF补题计划DAY1] Codeforces Round #737 (Div. 2) A~C

碎碎念

Awa了一发,卡B看题解又wa了几发,卡C根本不会组合数学直接看题解惹……对这种带位运算尤其异或的题天然恐惧(就像恐惧克总)

D似乎是线段树,(可恶啊根本不会) 什么时候才能菜出头啊呜呜呜

A. Ezzat and Two Subsequences

题意

将一个数组里的每个元素任意分配进两个集合之一,问两个集合分别求平均值的最大值

分析

贪心,对于数组中最大元素所在集合,此集合只存在它自己时的平均值最大,无论加入剩下任意元素都会使总平均值变小。

设最大元素的值为\(mx\),则

\[ans=\frac{(\sum _{i=1}^{n} a[i])-mx}{n-1}+mx \]

代码

#include<bits/stdc++.h>
using namespace std;
const int N=3e5+10;
int a[N],n,t;
main()
{
	cin>>t;
	while(t--)
	{
		cin>>n;
		for(int i=0;i<n;i++) cin>>a[i];
		sort(a,a+n);
		long double ans=0;
		for(int i=0;i<n-1;i++) ans+=a[i];
		ans=ans/(n-1)+a[n-1];
		cout<<setprecision(9)<<ans<<'\n';	
	} 
}

B. Moamen and k-subarrays

题意

一次操作,将长度为\(n\)且元素互不相同的数组分为\(k\)块,任意交换这\(k\)个数块的位置,能否使数组不降序排列。

分析

举几个栗子

\[ [1][3][2][4\ 5]->[1][2][3][4\ 5]\\ \\ [6\ 9\ 13][1\ 3]->[1\ 3][6\ 9\ 13] \]

可以看出我们要将在数组有序后仍然连续排列的数字划分进一个连续块(之前wa是我单纯地认为只要连续数字是升序就可以划分进同一个连续块),可以用结构体单开一个\(pos\)表示排序前数字所在位置,重新排列所需最小连续块数量\(sum\)初始为1,若排序后\(a[i-1].pos+1!=a[i].pos\) 则需新开一个连续块。否则不需分割。

代码

#include<bits/stdc++.h>
using namespace std;
const int N=3e5+10;
int n,k,t;
struct node{
    int v,p;
}a[N];
bool cmp(node a,node b)
{
    return a.v<b.v;
}
main()
{
	cin>>t;
	while(t--)
	{
		cin>>n>>k;
		int sum=1;
		for(int i=1;i<=n;i++){cin>>a[i].v;a[i].p=i;}
		sort(a+1,a+1+n,cmp);
		for(int i=2;i<=n;i++){if(a[i-1].p+1!=a[i].p) sum++;}
		if(sum<=k) puts("Yes");
		else puts("No");
	}
}

C. Moamen and XOR

题意

输出使n个二进制k位的数连续取&的结果大于等于这n个数连续取^的结果的方案数(模1e9+7)

分析

对于\(n\)个数的第\(i\)位,只有全部为1时取and的结果为1,偶数次xor结果为0,奇数次xor结果为1。

  • \(n\)为奇
    可知若某一位and的结果为1,则其xor的结果也必为1,要使题目条件成立,则对于每一位的取值只有以下两种情况。

    1.全为1
    2.有偶数个(包括0)个1
    由乘法原理可知
    方案数\(S_1=(1+C_n^0+C_n^2+C_n^4+……+C_n^{n-1})^k=(2^{n-1}+1)^k\)

  • \(n\)为偶
    可知若某一位and结果为1,则其xor的结果为0。

    1.使and结果==xor结果
    每一位均有偶数个1且不全为1。
    方案数\(S_2=(C_n^0+C_n^2+C_n^4+……+C_n^{n-2})^k=(2^{n-1}-1)^k\)

    2.使and结果>xor结果
    从第0位开始,枚举从低向高第\(i\)位,使其
    ①当前位全为1
    ②高位and结果与异或结果相等 \(=(C_n^0+C_n^2+C_n^4+……+C_n^{n-2})^{k-i-1}=(2^{n-1}-1)^{k-i-1}\)
    ③低位任取 \(=(C_n^0+C_n^1+C_n^2+……+C_n^n)^i=(2^n)^i\)
    此时当前位and结果为1,xor结果为0,且高位xor与and结果相等,则不管低位如何取,and结果一定大于xor结果。乘法原理得
    方案数\(S_3=(2^{n-1}-1)^{k-i-1}\times (2^n)^i\)

\[S=S_1+S_2+S_3 \]

代码

参考大佬代码时发现了快速幂的超好写方式……

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod=1e9+7;
int n,k,t;
int qmi(int a,int b)
{
    int res=1;
    for(;b;b>>=1,a=a*a%mod)
        if(b&1) res=(res*a)%mod;
    return res;
}

signed main()
{
    cin>>t;
    while(t--)
    {
        cin>>n>>k;
        int ans=0;
        if(n&1) ans=qmi(qmi(2,n-1)+1,k);
        else{
            ans=qmi(qmi(2,n-1)-1,k);
            for(int i=0;i<k;i++)
                ans=(ans+qmi(qmi(2,n),i)*qmi(qmi(2,n-1)-1,k-i-1)%mod)%mod;
        }
        cout<<ans<<'\n';
                
    }
}

D

依旧留坑,等我会线段树了再补orz

posted @ 2022-04-25 16:17  Hssliu  阅读(87)  评论(0)    收藏  举报