Codeforces Round #1323

A Even Subset Sum Problem

传送门:A


Description

给定数组 \(a\),求出它一个和为偶数的的非空子集,输出其元素编号,无解输出 \(-1\)。多组数据。


Solution

没有偶数且奇数个数必定无解。如果存在偶数,那么输出这个偶数就可以了。否则如果奇数个数超过 \(2\),输出两个奇数即可。

#include<bits/stdc++.h>
using namespace std;
const int N = 100 + 10;
int T;
int n,cnt,jsq;
int vis[N],a[N];
signed main()
{
    scanf("%d",&T);
    //T++;
    while(T--)
    {
        //cout << T << endl;
        cnt = jsq = 0;
        scanf("%d",&n);
        //cout << n << endl;
        for(int i = 1;i <= n;i++) vis[i] = 0;
        for(int i = 1;i <= n;i++)
            scanf("%d",&a[i]);
        for(int i = 1;i <= n;i++)
            if(a[i] & 1)  cnt++;
            else jsq++,vis[i] = 1;
        if(jsq == 0 and cnt < 2)
        {
            printf("-1\n");
            continue;
        }
        if(jsq)
        {
            printf("1\n");
            for(int i = 1;i <= n;i++)
                if(vis[i]){ printf("%d\n",i); break; }
        }
        else
        {
            int num = 0;
            printf("2\n");
            for(int i = 1;i <= n;i++)
            {
                if(vis[i]) continue;
                if(num)
                {
                    printf("%d\n",i);
                    break;
                }
                printf("%d ",i);
                num++;
            }
        }
    }
    return 0;
}

B Count Subrectangles

传送门:B


Description

给定长为 \(n\) 的数组 \(a\) 和长为 \(m\) 的数组 \(b\),数组中的元素均是 \(0\)\(1\)。有 \(n\times m\) 的矩阵 \(c\)\(c_{i,j}=a_i \cdot b_j\)。请求出矩阵 \(c\) 面积为 \(k\) 的全 \(1\) 子矩阵数量。样例及解释见题面。


Solution

维护一下横纵分别对于连续的长度为 \(x\)\(1\) 有多少个。然后对于 \(k\) 做质因数分解,用横纵的方案数做乘法原理即可。(注:代码中的二分是不必要的)

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 40000 + 10;
struct node
{
    int val,num;
}jk[2*N];
int n,m,k,cnt = 1,jsq,ans;
int a[N],b[N];
int fac[2*N];
int f[2*N],g[2*N];
bool cmp(node aa,node bb)
{
    return aa.val < bb.val;
}
signed main()
{
    memset(fac,0x3f,sizeof(fac));
    scanf("%lld%lld%lld",&n,&m,&k);
    for(int i = 1;i <= n;i++)
        scanf("%lld",&a[i]);
    a[n+1] = 0;
    for(int i = 1;i <= m;i++)
        scanf("%lld",&b[i]);
    b[m+1] = 0;
    for(int i = 1;i * i <= k;i++)
    {
        if(i * i == k) fac[++cnt] = i; 
        else if(k % i == 0)
        {
            fac[++cnt] = i;
            fac[++cnt] = k / i;
        }
    }
    for(int i = 2;i <= cnt;i++) jk[i].val = fac[i],jk[i].num = i;
    sort(jk + 2,jk + cnt + 1,cmp);
    for(int i = 1;i <= n + 1;i++)
    {
        if(a[i] == 0)
        {
            if(not jsq) continue;
            //flag1++;
            int l = 2,r = cnt + 1;
            while(r - l > 1)
            {
                int mid = (l + r) >> 1;
                if(jk[mid].val <= jsq) l = mid;
                else r = mid;
            }
            for(int j = 2;j <= l;j++)
                f[jk[j].num] += jsq - jk[j].val + 1;
            jsq = 0;
        }
        else jsq++;
    }
    jsq = 0;
    for(int i = 1;i <= m + 1;i++)
    {
        if(b[i] == 0)
        {
            if(not jsq) continue;
            //flag2++;
            int l = 2,r = cnt + 1;
            while(r - l > 1)
            {
                int mid = (l + r) >> 1;
                if(jk[mid].val <= jsq) l = mid;
                else r = mid;
            }
            for(int j = 2;j <= l;j++)
                g[jk[j].num] += jsq - jk[j].val + 1;
            //cout << jsq << endl;
            jsq = 0;
        }
        else jsq++;
    }
    int ox = sqrt(k);
    if(ox * ox == k) g[cnt+1] = g[cnt];
    for(int i = 2;i <= cnt;i++)
        ans += f[i] * g[i ^ 1];
    /*for(int i = 2;i <= cnt;i++) cout << f[i] << " ";
    cout << endl;
    for(int j = 2;j <= cnt;j++) cout << g[j] << " ";
    cout << endl;
    /*for(int i = 1;i <= cnt;i++) cout << fac[i] << " ";
    cout << endl;*/
    /*for(int i = 1;i <= n + 1;i++) cout << a[i] << " ";
    cout << endl;*/
    printf("%lld\n",ans);
    return 0;
}

C Unusual Competitions

传送门:C


Description

  • 有一个长度为 \(n\) 的括号序列。
  • 你可以进行若干次操作:花费 \(m\) 的代价,将一个长度为 \(m\) 的括号子串任意排列。
  • 若能将括号序列排成合法的括号序,请求出最小花费的代价和。否则请输出 -1。
  • \(1\leq n\leq 10^6\)

Solution

如果左括号数不等于右括号,则必然无解。从前向后扫,维护 \(sum_i\) 表示前 \(i\) 位左括号数与右括号数的差值。如果当前 \(sum_i < 0\),则当前出现了逆序,需要使用一次重排,我们打一个标记。当再次出现 \(sum_i = 0\) 时,我们统计它到上一次个数相同的位置的长度,累加进答案。顺序扫一遍即可。时间复杂度 \(O(n)\)

#include<bits/stdc++.h>
using namespace std;
const int N = 1000000 + 10;
int n,cnt,jsq,flag,pos,ans;
int sum[N];
char s[N];
signed main()
{
	scanf("%d",&n);
	scanf("%s",s + 1);
	for(int i = 1;i <= n;i++)
	    s[i] == '(' ? cnt++ : jsq++;
	if(cnt != jsq)
	{
		printf("-1\n");
		return 0;
	}
	for(int i = 1;i <= n;i++)
	{
		sum[i] = s[i] == '(' ? sum[i-1] + 1 : sum[i-1] - 1;
		if(sum[i] < 0) flag = 1;
		if(sum[i] == 0)
		{
			if(flag == 1)
				ans += i - pos;
			pos = i,flag = 0;
		}
	}
	printf("%d\n",ans);
	return 0;
}

D Present

传送门:D


Description

  • 给出一个长度为 \(n\) 的数列 \(a\)。其中第 \(i\) 项为 \(a_i\)​。
  • 请你求出 \(\bigoplus_{i=1}^{n}\bigoplus_{j=i+1}^{n}(a_i+a_j)\)。其中 \(\oplus\) 表示按位异或操作。
  • \(2\leq n\leq 4\times 10^5\)\(1\leq a_i \leq 10^7\)

Solution

求异或的话一般按位考虑。
对于第 \(k\) 位,考虑只有后面 \(k\) 位会对该答案产生影响,所以对 \(2^{k+1}-1\) 取模。
对于取完模的两个数为了使第 k 位为 \(1\),则和必在 \([2^k,2^{k+1}-1]\)\([2^k+2^{k+1},2^{k+2}-1]\) 之内。
排序后双指针维护满足的答案对数,判断奇偶即可维护出第 \(k\) 位。(注意位运算的优先辑,打括号)

#include<bits/stdc++.h>
using namespace std;
const int N = 400000 + 10;
int n,ans;
int a[N],t[N];
int cal(int ls,int rs)
{
    if(rs < ls) return 0;
    int l = 1,r = 1,res = 0;
    for(int i = n;i >= 1;i--)
    {
        while(l <= n and t[i] + t[l] < ls) l++;
        while(r <= n and t[i] + t[r] <= rs) r++; 
        if(i >= l and i < r) res += r - l - 1;
        else res += r - l;
    }
    return res >> 1 & 1;// 判断奇偶
}
int sol(int k)
{
    for(int i = 1;i <= n;i++)
        t[i] = a[i] & ((1 << (k + 1)) - 1);
    sort(t + 1,t + n + 1);
    return (cal(1 << k,(1 << (k + 1)) - 1) + cal(3 << k,(1 << (k + 2)) - 1)) & 1;
}
signed main()
{
    scanf("%d",&n);
    for(int i = 1;i <= n;i++) 
        scanf("%d",&a[i]);
    for(int i = 0;i <= 25;i++) ans |= sol(i) << i;
    printf("%d\n",ans);
    return 0;
}

E Instant Noodles

传送门:E

F Reality Show

传送门:F

posted @ 2021-12-13 14:09  一程山雪  阅读(42)  评论(0)    收藏  举报