Educational Codeforces Round 157 (Rated for Div. 2) A~D

A. Treasure Chest

扛着箱子能拿多远,拿多远

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define has1 __builtin_popcount
void solve()
{
    int x, y, k;
    cin >> x >> y >> k;
    if (y <= x)
    {
        cout << x << endl;
        return;
    }
    else
    {
        if (k >= (y - x))
        {
            cout << y << endl;
        }
        else
        {
            cout << y + (y - (x + k)) << endl;
        }
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

B. Points and Minimum Distance

排序后,相邻两个数,分别作为两个坐标的相同坐标值是最小的

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define has1 __builtin_popcount
void solve()
{
    int n;
    cin >> n;
    vector<int> a(2 * n);
    for (int i = 0; i < 2 * n; i++)
    {
        cin >> a[i];
    }
    sort(a.begin(), a.end());
    int sum = 0;
    for (int i = 1; i < n; i++)
    {
        sum += ((a[i] - a[i - 1]) + (a[i + n] - a[i + n - 1]));
    }
    cout << sum << endl;
    for (int i = 0; i < n; i++)
    {
        cout << a[i] << " " << a[i + n] << "\n";
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

C. Torn Lucky Ticket

赛时想着能不能冲过去,写了个时间复杂度O(n^3/2 ) ~O(n^2)的解法,直接timed out

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define has1 __builtin_popcount
const int N = 2e5 + 5;
int dp[N][6]; // dp[i][j]表示第i个字符串前j个数之和
int num[N];   // id[i]表示第i个字符串的长度
void solve()
{
    int n;
    cin >> n;
    vector<int> ji, ou;
    ll ans = 0;
    for (int i = 1; i <= n; i++)
    {
        string a;
        cin >> a;
        for (int j = 0; j < a.length(); j++)
        {
            dp[i][j + 1] = dp[i][j] + a[j] - '0';
        }
        num[i] = a.length();
        if (a.length() % 2 == 0)
        {
            ou.push_back(i);
        }
        else
        {
            ji.push_back(i);
        }
    }
    for (int i = 1; i <= n; i++)
    {
        if (num[i] % 2 == 1)
        {
            for (auto k : ji)
            {
                if (k == i)
                {
                    ans++;
                }
                else
                {
                    int avnum = (num[i] + num[k]) / 2;
                    if (num[i] == num[k])
                    {
                        if (dp[i][num[i]] == dp[k][num[k]])
                        {
                            ans++;
                        }
                    }
                    else if (num[i] < num[k])
                    {
                        if (dp[i][num[i]] + dp[k][avnum - num[i]] == dp[k][num[k]] - dp[k][avnum - num[i]])
                        {
                            ans++;
                        }
                    }
                    else
                    {
                        if (dp[i][avnum] == dp[k][num[k]] + dp[i][num[i]] - dp[i][avnum])
                        {
                            ans++;
                        }
                    }
                }
            }
        }
        else
        {
            for (auto k : ou)
            {
                if (k == i)
                {
                    ans++;
                }
                else
                {
                    int avnum = (num[i] + num[k]) / 2;
                    if (num[i] == num[k])
                    {
                        if (dp[i][num[i]] == dp[k][num[k]])
                        {
                            ans++;
                        }
                    }
                    else if (num[i] < num[k])
                    {
                        if (dp[i][num[i]] + dp[k][avnum - num[i]] == dp[k][num[k]] - dp[k][avnum - num[i]])
                        {
                            ans++;
                        }
                    }
                    else
                    {
                        if (dp[i][avnum] == dp[k][num[k]] + dp[i][num[i]] - dp[i][avnum])
                        {
                            ans++;
                        }
                    }
                }
            }
        }
    }
    cout << ans << endl;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t;
    // cin >> t;
    t = 1;
    while (t--)
    {
        solve();
    }
    return 0;
}

最后写了个map嵌套map的,再想想有没有更优解吧:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;

ll ans;
map<int,map<int,int> > mp; 
void fun(string s){
	ans++;
	int sum=0;
	ll lq,lh,sq=0,sh;
	for(int i=0;i<s.length();i++){
		sum+=(s[i]-'0');
	}
	for(int i=0;i<s.length();i++){
		sq+=(s[i]-'0');
		sh=sum-sq;
		lq=(i+1);
		lh=(s.length()-i-1);
		if(lq>lh){
			ans+=(mp[lq-lh][sq-sh]);
		}else if(lq<lh){
			ans+=(mp[lh-lq][sh-sq]);
		}
		if(i==s.length()-1){
			ans+=(mp[lq-lh][sq-sh]);
		}
	}
	sq=0;
	mp[s.length()][sum]++;
}
vector<string> vs;
bool cmp(string s1,string s2){
	return s1.length()<s2.length();
}
void solve() {
	mp.clear();
	int n;
	cin>>n;
	string s;
	ans=0;
	for(int i=0;i<n;i++){
		cin>>s;
		vs.push_back(s);
	}
	sort(vs.begin(),vs.end(),cmp);
	for(int i=0;i<n;i++){
		s=vs[i];
		fun(s);
	}
	cout<<ans<<"\n";
}
int main() {
    std::ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	int T = 1;
//    cin >> T;
	while (T--) {
        solve();
    }
    return 0;
}






D. XOR Construction

/*
给a数组做一个异或前缀和得到
a[0]^a[1],a[0]^a[2],a[0]^a[3]....a[0]^a[n-2]
相当于给a[1~n-1]都异或上了一个a[0]
那么根据题目要求,0~n-1必须在数组b中出现且仅一次
那么按照原来的正常情况下,对于二进制上的每一位,[0,n-1]中这一位应该有多少个1
由于:每个i都有b[i]^b[i+1]=a[i],那么就有b[i+1]=a[i]^b[i],递推式变化为:b[i+1]=a[i+1]^a[i]^..^a[0]^b[0],即为前缀a[i+1]^b[0]
讨论分析就可以知道b[0]在二进制表示下这一位是不是1,求出后再异或一下就是了
*/

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define has1 __builtin_popcount
void solve()
{
    int n;
    cin >> n;
    vector<int> a(n - 1);
    for (int i = 0; i < n - 1; i++)
        cin >> a[i];
    for (int i = 1; i < n - 1; i++)
        a[i] ^= a[i - 1];
    int x = 0;
    for (int i = 0; i < 20; i++)
    { // 枚举第几位
        int cnt[2]{}, target[2]{};
        for (int j = 0; j < n; j++) // 这一位应该有多少个1
        {
            target[j >> i & 1] += 1;
        }
        for (int j = 0; j < n - 1; j++) // 现在有多少个1
        {
            cnt[a[j] >> i & 1] += 1;
        }
        if (cnt[1] != target[1])
        {
            x |= 1 << i;
        }
    }
    cout << x << ' ';
    for (int i = 0; i < n - 1; i++)
        cout << (a[i] ^ x) << ' ';
    cout << '\n';
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t;
    // cin >> t;
    t = 1;
    while (t--)
    {
        solve();
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值