The 2018 ICPC Asia Qingdao Regional Programming Contest (C,E,F,J,M)

M. Function and Function

思路:经过比较小的操作后结果会陷入01循环,所以枚举即可.

代码:

#include <bits/stdc++.h>
using namespace std;
#pragma G++ optimize(2)
#define debug(x) cout << "[debug] " #x << " = " << x << '\n';
#define double long double
#define int long long
#define xiaowen ac
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 1e6 + 7;
const int P = 131;


/*
https://codeforces.com/gym/104270/problem/M

*/   
 map<int, int> mp;
int f(int x){
    string s = to_string(x);
    int ans = 0;
    for (int i = 0; i < s.length();i++){
        int k = s[i] - '0';
        ans += mp[k];
    }
    return ans;
}
void solve()
{

    mp[0] = 1, mp[1] = 0;
    mp[2] = 0, mp[3] = 0;
    mp[4] = 1, mp[5] = 0;
    mp[6] = 1, mp[7] = 0;
    mp[8] = 2, mp[9] = 1;
    int x, k;
    cin >> x >> k;
    int res = 0;
     while(k--){
         x = f(x);
         if(x==0){
            if(k & 1){
                cout << "1" << '\n';
                return;
            }else {
                cout << "0" << '\n';
                return;
            }
         }
     }
     cout << x << '\n';
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr), cout.tie(nullptr);

    int T;
    //T = 1;
     cin >> T;
    while (T--)
    {
        solve();
    }
    return 0;
}

J. Books

思路:当n==m时,直接输出 "Richman".否则统计数组中0的个数,因为这些是不需要付钱就可以获得的,也就是说我要买的书的数量应该大于等于数组中0的个数才符合要求,之后我们再求还需要买 的书的数量,记为k,直接买数组中除0外的前k个,代价为sum,设最后一个买的书的下标为 j,在求 [j+1,n]中的最小值,记为mi,答案就是sum+mi-1.(注意此题不能二分答案)

代码:

#include <bits/stdc++.h>
using namespace std;
#pragma G++ optimize(2)
#define debug(x) cout << "[debug] " #x << " = " << x << '\n';
#define double long double
#define int long long
#define xiaowen ac
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 1e6 + 7;
const int P = 131;

int n, m;
int a[N];
void solve()
{
    cin >> n >> m;
    for (int i = 1; i <= n;i++){
        cin >> a[i];
    }
    if(n==m){
        cout << "Richman" << '\n';
    }else {
        int cnt = 0;
        for (int i = 1; i <= n;i++){
            if(a[i]==0){
                cnt++;
            }
        }
        if(cnt > m){
            cout << "Impossible" << '\n';
        }else {
            int k = m - cnt;
            int sum = 0;
            int mi = 1e18;
            for (int i = 1; i <= n;i++){
               if(a[i]==0)continue;
               if(k > 0){
                   sum += a[i];
                   k--;
               }else {
                   mi = min(mi, a[i]);
               }
            }
            cout << (sum + mi - 1) << '\n';
        }
    }
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr), cout.tie(nullptr);

    int T;
    // T = 1;
    cin >> T;
    while (T--)
    {
        solve();
    }
    return 0;
}

C. Flippy Sequence

思路:分类讨论 

先判断初始时s是否等于t ,若s == t,res=(n*(n+1))/2,否则求s 与 t 的异或数组 a[],求a中连续一的个数,记为cnt。先特判n==1的情况,之后当cnt >= 3时,显然无解.当cnt == 2时,发现结果是 6 ,当 cnt == 1时,记1的个数为k,res=(k-1)*2+(n-k)*2.  (1贡献的方案数加上0贡献的方案数)

代码:

#include <bits/stdc++.h>
using namespace std;
#pragma G++ optimize(2)
#define debug(x) cout << "[debug] " #x << " = " << x << '\n';
#define double long double
#define int long long
#define xiaowen ac
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 1e6 + 7;
const int P = 131;

int n;
string s, t;
int a[N];
void solve()
{
    cin >> n;
    cin >> s;
    cin >> t;
    // 求 s与t的异或数组
    for (int i = 0; i < n;i++){
        a[i] = (s[i] - '0') ^ (t[i] - '0');
    }
    if(s==t){
        cout << (n * (n + 1)) / 2 << '\n';
        return;
    }else {
        if(n==1){
            // 0 1 或 1 0 
            cout << "0" << '\n';
            return;
        }
        // 根据连续1的个数进行分类讨论
        int cnt = 0;
        for (int i = 0; i < n;i++){
            if(a[i]==1){
                int j = i;
                cnt++;
                while(j < n && a[j]==1){
                    j++;
                }
                i = j - 1;
            }
        }
        if(cnt >= 3){
            // 根据鸽笼原理,无解
            cout << "0" << '\n';
        }else if(cnt == 2){
            // 手推发现只有6种情况
            cout << "6" << '\n';
        }else if(cnt == 1){
            int k = 0;// 表示1的个数
            for (int i = 0; i < n;i++){
                k += (a[i] == 1);
            }
            int res =(k-1)*2+ (n - k) * 2;
            cout << res << '\n';
        }
    }
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr), cout.tie(nullptr);

    int T;
    //T = 1;
     cin >> T;
    while (T--)
    {
        solve();
    }
    return 0;
}

E. Plants vs. Zombies

思路:二份答案

代码:

#include <bits/stdc++.h>
using namespace std;
#pragma G++ optimize(2)
#define debug(x) cout << "[debug] " #x << " = " << x << '\n';
#define double long double
#define int long long
#define xiaowen ac
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 1e6 + 7;
const int P = 131;

// 二分答案
int n, m;
int a[N];
int b[N];

bool check(int x){
    // 需要边走边更新  b[i]次数可能会因为浇水而减小
    for (int i = 0; i <= n + 3;i++){
        b[i] = 0;
    }
    int ans = 0;
    for (int i = 1; i <= n;i++){
        if(x > b[i]){
            int t = x - b[i];
            t = (t + a[i] - 1) / a[i];
            ans += t * 2 - 1;
            if(ans > m){
                return false;
            }
            b[i + 1] += a[i + 1] * (t - 1);
        }else {
            ans++;
        }
    }
    return true;
}
void solve()
 {
        cin >> n >> m;
        for (int i = 1; i <= n; i++)
        {
            cin >> a[i];
        }
        int res = 0;
        int l = 0, r = 1e18;
        while (l <= r)
        {
            int mid = (l + r) / 2;
            if (check(mid))
            {
                l = mid + 1;
                res = max(res, mid);
            }
            else
            {
                r = mid - 1;
            }
        }
        cout << res << '\n';
    }

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr), cout.tie(nullptr);

    int T;
     // T = 1;
   cin >> T;
    while (T--)
    {
        solve();
    }
    return 0;
}

F. Tournament

思路:打表找规律,VP时没写出来

代码:

#include <bits/stdc++.h>
using namespace std;
#pragma G++ optimize(2)
#define debug(x) cout << "[debug] " #x << " = " << x << '\n';
#define double long double
#define int long long
#define xiaowen ac
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 1e6 + 7;
const int P = 131;


void solve()
{
    int n, k;
    cin >> n >> k;
    int down = (n & (-n));
    if(k >= down){
        cout << "Impossible" << '\n';
    }else {
        for (int i = 1; i <= k;i++){
            for (int j = 0; j < n;j++){
                if(j != n-1){
                    cout << ((i ^ j) + 1) << " ";
                }else {
                    cout << ((i ^ j) + 1) << '\n';
                }
            }
        }
    }
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr), cout.tie(nullptr);

    int T;
    //T = 1;
     cin >> T;
    while (T--)
    {
        solve();
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值