Codeforces Round #720 (Div. 2) [未完待续]

A. Nastia and Nearly Good Numbers

题目描述
image
image

参考题解

x + y = z, 两边把因子A消去 =>
x/A + y/A = z/A
要求其中只有一个可以含有因子B, 可以如下构造:
x/A = B, y/A = B+1, z/A = 2B+1
当B不为1时用数论知识很容易得到B+1无因子B, 2B+1不含因子B
(证明方法注: B+1 === 2B+1 === 1 (mod B), '==='表示同余)

#include <iostream>
#include <cstdio>

using namespace std;

typedef long long LL;

int main()
{
    int t;
    cin >> t;
    while(t --)
    {
        int A, B;
        scanf("%d%d", &A, &B);
        if(B == 1)
        {
            printf("NO\n");
        }
        else
        {
            printf("YES\n");
            printf("%lld %lld %lld\n", A*(LL)B, A*(LL)(B+1), A*(LL)(2*B+1));
        }
    }
    return 0;
}

B. Nastia and a Good Array

题目描述
image
image

参考题解

从最小数的位置开始往两边自增1,构造题

#include <iostream>
#include <cstdio>
#include <queue>
#include <vector>
#include <cstring>
#define x first
#define y second
using namespace std;
const int N = 1e5+5, INF = 0x3f3f3f3f;
typedef long long LL;
typedef pair<int, int> PII;

int n;
int a[N];

int gcd(int a, int b)
{
    return b ? gcd(b, a%b) : a;
}

struct RES
{
    int i, j, x, y;
} res[N];

int main()
{
    int t;
    cin >> t;
    while(t --)
    {
        int ans = 0;
        cin >> n;
        int minidx = -1;
        for(int i = 0; i < n; ++ i)
        {
            scanf("%d", a+i);
            if(minidx == -1 || a[i] < a[minidx])
            {
                minidx = i;
            }
        }
        for(int i = minidx-1; i >= 0; -- i)
        {
            res[ans++] = {i, minidx, a[i+1]+1, a[minidx]};
            a[i] = a[i+1] + 1;
        }
        for(int i = minidx+1; i < n; ++ i)
        {
            res[ans++] = {minidx, i, a[minidx], a[i-1]+1};
            a[i] = a[i-1] + 1;
        }
        printf("%d\n", ans);
        for(int i = 0; i < ans; ++ i)
        {
            printf("%d %d %d %d\n", res[i].i+1, res[i].j+1, res[i].x, res[i].y);
        }
    }
    return 0;
}

C. Nastia and a Hidden Permutation

题目描述
image
image
image

参考题解

感谢大佬提供的思路
自己的思路图
image

#include <iostream>
#include <cstdio>
#include <set>
#include <cstring>
using namespace std;

const int N = 1e4+5;

int n;

int ask(int t, int i, int j, int x)
{
    printf("? %d %d %d %d\n", t, i, j, x);
    cout.flush();
    int res = -1;
    scanf("%d", &res);
    return res;
}

int ans[N];

int main()
{
    int t;
    cin >> t;
    while(t --)
    {
        memset(ans, 0, sizeof(ans));
        scanf("%d", &n);
        for(int i = 1; i <= n/2; ++ i)
        {
            int a = i, b = i+n/2;
            //计算maxv
            int maxv = -1;
            int t = ask(1, a, b, n-1);
            if(t == -1) return 0; //错误
            if(t == n-1)
            {
                int tp = ask(2, a, b, n-1);
                if(tp == -1)    return 0;
                if(tp == n)
                {
                    ans[a] = n;
                }
                else
                {
                    maxv = t;
                }
            }
            else
            {
                maxv = t;
            }
            if(maxv == -1) //已经计算ans[a]
            {
                ans[b] = ask(2, b, a, 1);
                if(ans[b] == -1)    return 0;
                continue;
            }
            //计算minv
            int minv = -1;
            t = ask(2, a, b, 1);
            if(t == -1) return 0;
            if(t == 2)
            {
                int tp = ask(1, a, b, 1);
                if(tp == -1)    return 0;
                if(tp == 1)
                {
                    ans[b] = 1;
                }
                else
                {
                    minv = t;
                }
            }
            else
            {
                minv = t;
            }
            if(minv == -1) //已经计算了ans[b]
            {
                ans[a] = ask(1, b, a, n-1);
                if(ans[a] == -1)    return 0;
                continue;
            }
            //计算结果
            t = ask(2, a, b, minv);
            if(t == -1) return 0;
            if(t == minv)
            {
                ans[a] = minv;
                ans[b] = maxv;
            }
            else
            {
                ans[a] = maxv;
                ans[b] = minv;
            }
        }
        if(n%2==1)
        {
            set<int> ha;
            for(int i = 1; i <= n/2*2; ++ i)
            {
                ha.insert(ans[i]);
            }
            for(int i = 1; i <= n; ++ i)
            {
                if(ha.count(i) == 0)
                {
                    ans[n] = i;
                    break;
                }
            }
        }
        printf("!");
        for(int i = 1; i <= n; ++ i)
        {
            printf(" %d", ans[i]);
        }
        printf("\n");
        cout.flush();
    }
    return 0;
}
posted @ 2021-05-10 01:03  chaosliang  阅读(49)  评论(0)    收藏  举报