$CF\ 639\ (Div\ 2)$

\(CF\ 639\ (Div2)\)

\(A.\)

判断给定拼图是否可拼

找规律发现,只有 \(1\times m,\ n\times 1,\ 2\times 2\) 的可行

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <math.h>
#include <algorithm>
#include <vector>
#define fi first
#define se second
#define pii pair<int, int>
#define pb push_back
#define arrayDebug(a, l, r) for(int i = l; i <= r; ++i) printf("%d%c", a[i], " \n"[i == r])
typedef long long LL;
typedef unsigned long long ULL;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;
const int DX[] = {0, -1, 0, 1, 0, -1, -1, 1, 1};
const int DY[] = {0, 0, 1, 0, -1, -1, 1, 1, -1};
const int MOD = 1e9;
const int N = 5e5 + 7;
const double PI = acos(-1);
const double EPS = 1e-6;
using namespace std;
inline int read()
{
    char c = getchar();
    int ans = 0, f = 1;
    while(!isdigit(c)) {if(c == '-') f = -1; c = getchar();}
    while(isdigit(c)) {ans = ans * 10 + c - '0'; c = getchar();}
    return ans * f;
}
 
int t;
int main()
{
    t = read();
    while(t--) {
        int n = read(), m = read();
        if(n == 1 || m == 1 || m == 2 && n == 2) puts("YES");
        else puts("NO");
    }
    return 0;
}
/*
5 5
1 2
2 5
5 4
4 3
3 1
*/

\(B.\)

给定高度为 \(h\) 的卡堆的堆积方式以及 \(n\) 张卡片,优先建造高度最高的卡堆,计算可构造的卡堆的最大数量

\(dp[i]\) 表示高度为 \(i\) 的卡堆所需卡片数量,找规律发现

\[dp[i] = dp[i - 1] + 3 i - 1 \]

预处理各个卡堆所需要的卡片数量,对于当前的 \(n\),不断二分查找可构造的最大卡堆即可

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <math.h>
#include <algorithm>
#include <vector>
#define fi first
#define se second
#define pii pair<int, int>
#define pb push_back
#define arrayDebug(a, l, r) for(int i = l; i <= r; ++i) printf("%d%c", a[i], " \n"[i == r])
typedef long long LL;
typedef unsigned long long ULL;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;
const int DX[] = {0, -1, 0, 1, 0, -1, -1, 1, 1};
const int DY[] = {0, 0, 1, 0, -1, -1, 1, 1, -1};
const int MOD = 1e9;
const int N = 1e5 + 7;
const double PI = acos(-1);
const double EPS = 1e-6;
using namespace std;
inline int read()
{
    char c = getchar();
    int ans = 0, f = 1;
    while(!isdigit(c)) {if(c == '-') f = -1; c = getchar();}
    while(isdigit(c)) {ans = ans * 10 + c - '0'; c = getchar();}
    return ans * f;
}
 
int t;
LL dp[N];
int main()
{
    dp[1] = 2;
    int cnt = 0;
    for(int i = 2; i <= N; ++i) {
        cnt++, dp[i] = dp[i - 1] + 3 * i - 1;
        if(dp[i] >= 1000000000) break;
    }
    //for(int i = 1; i <= cnt; ++i) dp[i] += dp[i - 1];
    t = read();
    while(t--) {
        int n = read();
        int ans = 0;
        while(n) {
            int p = upper_bound(dp + 1, dp + 1 + cnt, n) - dp;
            p--;
            if(p > 0 && dp[p] <= n) ans++, n -= dp[p];
            else break;
        }
        printf("%d\n", ans);
    }
    return 0;
}
/*
5
3
14
15
24
1
*/

\(C.\)

有无限个房间,每个房间对应唯一一个数字,每个房间初始有一个客人

给定长为 \(n\) 的整数序列 \(a\)

现在移动客人,将 \(k\) 房间内的客人移动到房间 \(k + a_{k\ mod\ n}\),询问移动后是否仍然满足每个房间至多只有 \(1\) 个客人

假设 \(a_{k\ mod\ n} = a_{0}\),当然也可以等于其他位置

考虑移动的映射关系

\(k\rightarrow k + a_{k\ mod\ n} = k + a_{0}\)

\(k + 1\rightarrow k + 1 + a_{(k + 1)\ mod\ n} = k + 1 + a_{1}\)

\(k + 2\rightarrow k + 2 + a_{(k + 2)\ mod\ n} = k + 2 + a_{2}\)

\(...\)

\(k + n - 1\rightarrow k + n - 1 + a_{(k + n - 1)\ mod\ n} = k + n - 1 + a_{n - 1}\)

\(k + n\rightarrow k + n + a_{(k + n)\ mod\ n} = k + n + a_{0}\)

分析得到,只需要 \(i + a[i],\ i = 0,\ 1,\ ...,\ n - 1\) 构成模 \(n\) 的一个最小非负完全剩余系即可

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int, int>
#define pb push_back
#define arrayDebug(a, l, r) for(int i = l; i <= r; ++i) printf("%d%c", a[i], " \n"[i == r])
typedef long long LL;
typedef unsigned long long ULL;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;
const int DX[] = {0, -1, 0, 1, 0, -1, -1, 1, 1};
const int DY[] = {0, 0, 1, 0, -1, -1, 1, 1, -1};
const int MOD = 1e9;
const int N = 2e5 + 7;
const double PI = acos(-1);
const double EPS = 1e-6;
using namespace std;
inline int read()
{
    char c = getchar();
    int ans = 0, f = 1;
    while(!isdigit(c)) {if(c == '-') f = -1; c = getchar();}
    while(isdigit(c)) {ans = ans * 10 + c - '0'; c = getchar();}
    return ans * f;
}

int t;
LL n, a[N];
int main()
{
    t = read();
    while(t--) {
        n = read();
        for(int i = 0; i < n; ++i) scanf("%lld", &a[i]);
        set<LL> st;
        for(int i = 0; i < n; ++i) {
            st.insert(((a[i] + i) % n + n) % n);
        }
        if(st.size() == n) puts("YES");
        else puts("NO");
    }
    return 0;
}
/*
5
3
14
15
24
1
*/

这题想通了还是挺有意思的 😄

posted @ 2020-05-09 00:16  徐摆渡  阅读(187)  评论(0编辑  收藏  举报