Codeforces Round #750 (Div. 2)A-F1补题题解

A

**题目描述:**有 a 首 1分钟的歌,b 首 2 分钟的歌,c首 3 分钟的歌。要分在两场音乐会,问最小的差是多少。
这道题的关键是题上说a,b,c,均不为0,这样的话三种歌总能被独立的分在两场音乐会因为2、3+1都能被2整除,这样最后两场音乐会的差值一定是0或1,答案为sum&1.

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int main(){
	int t;
	scanf ("%d",&t);
	while (t--)
	{
		int a,b,c;
		long long sum=0;
		scanf ("%d%d%d",&a,&b,&c);
		   sum = a+2*b+c*3;
		   
		   printf ("%lld\n",sum&1);	
	}
	return 0;
}

B

题目描述:
给你一个数组让你求有多少个子序列满足和为整个数组的和减一。
一看就是只有1,0的个数会对答案有贡献,答案为1的个数乘上2的0的个数的次方个。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long LL;
LL n,m;
int h[100];
LL quick(LL a,LL b)
{
	LL res=1;
	while (b)
	{
		if (b&1) res*=a;
		a*=a;
		b>>=1;
	}
	return res;
}
int main()
{
	int t;
	scanf ("%d",&t);
	while (t--)
	{
		n = m = 0;
		int u;
		scanf ("%d",&u);
		for (int i=1;i<=u;i++)
		{
			scanf ("%d",&h[i]);
			if (h[i]==1)
			n++;
			else if (h[i]==0)
			m++;
		}
		if (n==0) cout<<0<<endl;
		else
		{
			long long res = n*quick(2,m);
			printf ("%lld\n",res);
		}
	}
	return 0;
}

C

题目描述:
卡帕奶奶决定织一条围巾,并请谢尔爷爷为它做一个图案,图案是由小写的英文字母组成的字符串。舍爷爷写了一个长度为n的字符串s。卡帕奶奶想织一条漂亮的围巾,在她看来,一条漂亮的围巾只能用回文的线织出来。她想改变谢尔爷爷写的模式,但为了避免冒犯他,她会选择一个小写的英文字母,然后擦掉一些(由她自己选择,可能没有或全部)在字符串s中出现的那个字母她还想尽量减少图案中被抹去的符号的数量。请帮助她,找出她能擦掉的最少符号数,让字符串变成回文,或者告诉她这是不可能的。注意,她只能擦掉与她选择的一个字母相等的符号一个字符串是一个回文,如果它从左到右和从右到左是相同的。例如,字符串’kek’ ‘abacaba’, 'r’和’papicipap’是回文,而字符串而“abb”和“iq”则不是。
+++++++++++++++++++++++++++++=+++++++
思路: 这里得想明白一件事就简单了,就是在判断回文串时一旦某一位产生了失配,那么如果现在解决不了,那么无论后面怎样进行删除操作,他还是失配。这样这个题就简单了,如果失配就直接删除再去判断,不能删除直接就直接这种情况就不行了。

#include <bits/stdc++.h>

using namespace std;
const int N = 1e5+5;
char ch[N];
int rt[30];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        int ans=0;
        scanf("%d%s",&n,ch+1);
        int minn = 0x3f3f3f3f;
        for(int i = 0;i < 26;i++)
        {
            int l=1,r=n,ac=1;
            ans = 0;
            while(l<=r)
            {
                if(ch[l]==ch[r]) ++l,--r;
                else if(ch[l]==i+'a') ++l,++ans;
                else if(ch[r]==i+'a') --r,++ans;
                else
                {
                    ac=0;
                    break;
                }
            }
            if(ac)
            minn=min(minn,ans);
        }
        if (minn==0x3f3f3f3f)
        printf("-1\n");
        else
        printf("%d\n",minn);
    }
    return 0;
}

D

两个数的情况我们很好想,各自乘另一个数的相反数就行了,那么三个数其实跟两个数一样,我们只需想成一个a+b,一个c就行了。因为数组中不能出现0,所以进行一下特判就行了。

#include<bits/stdc++.h>
using namespace std;

int main() {
	int t; cin >> t;
	while (t --) {
		int n; cin >> n;
		vector<int> a(n);
		for (int i = 0; i < n; i ++) cin >> a[i];
		int s = 0;
		if (n & 1) {
			if (a[0] + a[1] != 0) cout << -a[2] << ' ' << -a[2] << ' ' << (a[0] + a[1]) << ' ';
			else if (a[1] + a[2] != 0) cout << (a[1] + a[2]) << ' ' << -a[0] << ' ' << -a[0] << ' ';
			else cout << -a[1] << ' ' << (a[0] + a[2]) << ' ' << -a[1] << ' ';
			s = 3;
		}
		while (s < n) {
			cout << -a[s + 1] << ' ' << a[s] << ' ';
			s += 2;
		}
		cout << '\n';
	}
	return 0;
}

E

队友补的,直接粘上

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int N = 2e5+10;

int T, n, a, tmp, ans;
ll s[N], sup[2][N];

int main()
{
    cin >> T;
    while (T--)
    {
        scanf("%d", &n);
        sup[0][n + 1] = sup[1][n + 1] = 0;
        tmp = 0, ans = 1;
        for (int i = 1; i <= n; ++i)
            scanf("%d", &a), s[i] = s[i - 1] + a;
        
        for (int i = n; i > 0; --i)
            sup[tmp][i] = max(sup[tmp][i + 1], s[i] - s[i - 1]);
        for (int t = 2; t <= n; ++t, tmp ^= 1)
        {
            for (int i = n; i > 0; --i)
                if (i + t <= n && sup[tmp][i + t] > s[i + t - 1] - s[i - 1])
                    sup[tmp ^ 1][i] = max(sup[tmp ^ 1][i + 1], s[i + t - 1] - s[i - 1]);
                else
                    sup[tmp ^ 1][i] = sup[tmp ^ 1][i + 1];
            if (sup[tmp ^ 1][1])
                ans = t;
            else
                break;
            memset(sup[tmp],0,sizeof(sup[tmp]));
        }
        printf("%d\n", ans);
    }
    return 0;
}

F1

**题目大意:**让你求给定数组所有递增子序列的异或和有哪些。

思路:想到DP,但是n方决定过不了,因为数据的范围小,异或和最多到2的9次方为512,这样可以直接
二层循环枚举异或和,状态的转移很好想到。

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 1e5+10;
int a[N];
int f[520],g[520];
int main()
{
	memset(g,0x3f3f3f3f,sizeof g);
	memset(f,0,sizeof f);
	int n;
	scanf ("%d",&n);
	for (int i=0;i<n;i++){
		scanf ("%d",&a[i]);
		f[a[i]] = 1;
	}
	f[0] = 1;
	for (int i=0;i<n;i++)
	{
		g[a[i]] = min(a[i],g[a[i]]);
		for (int j=0;j<512;j++)
		{
			if (f[j]&&a[i]>g[j])
			{
				f[a[i]^j] = 1;
				g[a[i]^j] = min(a[i],g[a[i]^j]);
			}
		}
	}
	int res = 0;
	for (int i=0;i<512;i++)
	  if (f[i])
	    res++;
	cout<<res<<endl;
	for (int i=0;i<512;i++)
	  if (f[i])
	     cout<<i<<' ';
	return 0;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值