暑假集训七[One, 砖块,数字,甜圈]

暑假集训七

和迪哥推了一个多小时,终于被贯通

  • 方法一
here
#include <bits/stdc++.h>
#define LL long long
#define Re register int
#define LD long double
#define mes(x, y) memset(x, y, sizeof(x))
#define cpt(x, y) memcpy(x, y, sizeof(x))
#define fuc(x, y) inline x y
#define fr(x, y, z)for(long long x = y; x <= z; x ++)
#define fp(x, y, z)for(long long x = y; x >= z; x --)
#define frein(x) freopen(#x ".in", "r", stdin)
#define freout(x) freopen(#x ".out", "w", stdout)
#define ki putchar('\n')
#define fk putchar(' ')
#define WMX aiaiaiai~~
#define pr pair<long long, long long>
#define mk(x, y) make_pair(x, y)
using namespace std;
namespace kiritokazuto{
    auto read = [](){
        LL x = 0;
        int f = 1;
        char c;
        while (!isdigit(c = getchar())){ if (c == '-')f = -1; }
        do{ x = (x << 1) + (x << 3) + (c ^ 48); } while (isdigit(c = getchar()));
        return x * f;
    };
    template <typename T> fuc(void, write)(T x){
        if (x < 0)putchar('-'), x = -x;
        if (x > 9)write(x / 10); putchar(x % 10 | '0');
    }
}

using namespace kiritokazuto;

bool Mbg = false;
const int maxn = 1e7 + 1000, Mod = 998244353;
const int Inf = 2147483647;
bool Med = true;
//先打个暴力,等会用来拍把
int per[maxn];
int pos;
int turn;
int t, n;
int vis[maxn];
int cnt;
int main(){
    // frein(data);
    // freout(A);
    t = read();
    int x = 0;
    while (t--){
        n = read();
        x = 0;
        fr(i, 2, n) x = (n - i + 1 + x) % i;
        write(x + 1);
        ki;
    }

    // if (1.0 * (&Mbg - &Med) / 1024 / 1024 > 0.1) fprintf(stderr, "memo: %lf MB\n", 1.0 * (&Mbg - &Med) / 1024 / 1024);
    // else fprintf(stderr, "memo: %lf KB\n", 1.0 * (&Mbg - &Med) / 1024);
    // fprintf(stderr, "time: %lf s\n", 1.0 * (clock() - _tme) / CLOCKS_PER_SEC);
}
  • 解释一下那个柿子
    • 假设我上一把死的人的位置在\(x\),即它上一把的编号为\(x\),那么我序列总共还剩下两种数字
      • \(id > x\)
      • \(id < x\)
    • 考虑他们在新序列里边的编号
      • \(id > x\) \(id_{new} = id - x\)
      • \(id < x\) \(id_{new} = id - n_{old} + x\)
    • 手摸一下很显然
    • 然后我们就可以考虑将两个柿子合并,
      因为\(id > x\)\(id - x\)一定大于\(0\),所以它加一个\(n_{old}\)再模一个\(n_{old}\)值是不变的,所以两个柿子可以都合并为

\[ id_{new} = (id - n_{old} + x)\ \% \ n_{old} \]

  • 方法二
here
// 线性求约瑟夫问题
// 倒着推
// 刚开始只有一个人,最后一个死的在他前面
// 然后从那个人开始,判断谁是这一轮开始数的,那么再上一个死的人就是这一轮的开始的人的前一个
// 以此类推
#include <bits/stdc++.h>
#define re register
#define ll long long
#define ull unsigned long long 
using namespace std;
inline int read()
{
    int x = 0, f = 0; char c = getchar();
    while (c < '0' || c > '9') f = c == '-', c = getchar();
    while (c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c & 15), c = getchar();
    return f ? -x : x;
}

int n, T;

int main()
{
    T = read();
    while (T--)
    {
        n = read();
        int cnt = 1, now = 1; // 总人数,当前这一轮第一个数的人
        for (re int i = n - 1; i >= 1; --i)
        {
            ++cnt, ++now; // 总人数加加,然后now是这一轮第一个数的,所以复活他前面那个死的人
            // 接下来倒着数,看是谁那么阴险把前面那个人数死了
            now -= i % cnt; // 删去循环,然后往前数
            if(now < 1) now += cnt;
        }
        printf ("%d\n", n - now + 1); // 最后的now是第一个人,每次我们都是往前面复活人,所以n是最后一个活的人
    }
    return 0;
}
  • 首先解释变量
    • \(now\)即是当前局数一的人的位置,那么我推到第一局之后\(now\)不就是序号为一的人的位置嘛(第一句序号为\(1\)的人数\(1\))
    • \(tot\)是当前局的总人数
    • 那么答案为啥是\(n - now + 1\) ?
      • 这个方法的思路是将整个环从最后活着的那个人那里断开,则相当于是将它固定在\(n\)的位置,将复活的人一直向它左边插入,那么最终\(n\)\(pos\)的距离就是编号\(1\)和它编号的距离
      • 循环内部\(now++\)是因为我\(now\)为当前局数一的人的位置,那么它加加则是上一局死的人的位置,我们考虑如何推出上一局的\(now\),因为我们是倒序枚举的,那么上一局要杀的人的编号就是\(i\)
      • 我先将\(i \% tot\),即是假如是从上一局数一的人开始,先将能走的圈走完,最后剩下的就是我和这一把要死的人之间的距离,然后就很显然了

砖块

  • 一个sb小模拟,赛时没有调出来,因为我本来觉得\(STL\)太慢,没用\(Map\), 用两个数组处理的负数的情况,但是分类讨论的太多了...然后当我打到\(100\)多行的时候已经为时已晚了....
  • 就是记住开始的时候\(mp[make\_pair(0, 0)]++\)
here
#include <bits/stdc++.h>
#include <bits/extc++.h>
#define LL long long
#define Re register int
#define LD long double
#define mes(x, y) memset(x, y, sizeof(x))
#define cpt(x, y) memcpy(x, y, sizeof(x))
#define fuc(x, y) inline x y
#define fr(x, y, z)for(long long x = y; x <= z; x ++)
#define fp(x, y, z)for(long long x = y; x >= z; x --)
#define frein(x) freopen(#x ".in", "r", stdin)
#define freout(x) freopen(#x ".out", "w", stdout)
#define ki putchar('\n')
#define fk putchar(' ')
#define WMX aiaiaiai~~
#define pr pair<long long, long long>
#define mk(x, y) make_pair(x, y)
using namespace std;
namespace kiritokazuto{
    auto readd = [](){
        LL x = 0;
        int f = 1;
        char c;
        while (!isdigit(c = getchar())){ if (c == '-')f = -1; }
        do{ x = (x << 1) + (x << 3) + (c ^ 48); } while (isdigit(c = getchar()));
        return x * f;
    };
    template <typename T> fuc(void, write)(T x){
        if (x < 0)putchar('-'), x = -x;
        if (x > 9)write(x / 10); putchar(x % 10 | '0');
    }
}

using namespace kiritokazuto;

bool Mbg = false;
const int maxn = 1e6 + 1000, Mod = 998244353;
const int Inf = 2147483647;
bool Med = true;
int t;

int len = 0;
char s[102];
int Max;
__gnu_pbds::list_update <pr, int> mp;
int type;//2为立着,1为竖着躺,0为横着躺
int Xmax, Ymax, Xmin = 0, Ymin = 0;
fuc(int, changetype)(int lasttype, int opt){
    //1 "N" 2"S" 3"W" 4"E"
    if (opt == 1){
        if (lasttype == 2) return 1;
        if (lasttype == 1)return 2;
        if (lasttype == 0)return 0;
    }
    if (opt == 4){
        if (lasttype == 2) return 0;
        if (lasttype == 1)return 1;
        if (lasttype == 0)return 2;
    }
    if (opt == 3){
        if (lasttype == 2) return 0;
        if (lasttype == 1)return 1;
        if (lasttype == 0)return 2;
    }
    if (opt == 2){
        if (lasttype == 2) return 1;
        if (lasttype == 1)return 2;
        if (lasttype == 0)return 0;
    }
}
fuc(void, docnt)(int xmax, int ymax, int xmin, int ymin){//忘了vscode有调试这个东西了,最后还是负数爆了
    if (ymax == ymin){
        fr(i, xmin, xmax){
            // cnt[i][ymin]++;
            mp[mk(i, ymin)]++;
            Max = max(Max, mp[mk(i, ymin)]);
        }
        return;
    }
    if (xmax == xmin){
        fr(i, ymin, ymax){
            // cnt[xmax][i]++;
            mp[mk(xmax, i)]++;
            Max = max(Max, mp[mk(xmax, i)]);
        }
    }
}

int main(){
    // frein(in);
    //  freout(out2);
    //2为立着,1为竖着躺,0为横着躺
    t = readd();
    while (t--){
        // mes(cnt, 0);
        mp.clear();
        mp[mk(0, 0)] = 1;
        len = readd();
        Max = 1;
        type = 2;
        scanf("%s", s + 1);
        int slen = strlen(s + 1);
        Xmax = 0;
        Ymax = 0;
        Xmin = 0, Ymin = 0;
        fr(i, 1, slen){
            if (s[i] == 'E'){
                int lasttype = type;
                type = changetype(type, 4);
                if (lasttype == 2){
                    Xmax = Xmax + len;
                    Ymax = Ymax;
                    Xmin = Xmin + 1;
                    Ymin = Ymin;
                    // printf("Now3 && 5 && 20 && 22 && 26Xmax = %d Xmin = %d Ymax = %d, Ymin = %d\n", Xmax, Xmin, Ymax, Ymin);
                    docnt(Xmax, Ymax, Xmin, Ymin);
                }
                if (lasttype == 1){
                    Xmax = Xmax + 1;
                    Xmin = Xmax;
                    Ymax = Ymax;
                    Ymin = Ymin;
                    docnt(Xmax, Ymax, Xmin, Ymin);
                }
                if (lasttype == 0){
                    Xmax = Xmax + 1;
                    Xmin = Xmax;
                    Ymax = Ymax;
                    Ymin = Ymin;
                    // printf("Now4 && 7 && 19 && 21&& 23Xmax = %d Xmin = %d Ymax = %d, Ymin = %d\n", Xmax, Xmin, Ymax, Ymin);
                    docnt(Xmax, Ymax, Xmin, Ymin);
                }
            }
            if (s[i] == 'N'){
                int lasttype = type;
                type = changetype(type, 1);
                // printf("Now2 Xmax = %d Xmin = %d Ymax = %d, Ymin = %d\n", Xmax, Xmin, Ymax, Ymin);
                // printf("type == %d\n", type);
                if (lasttype == 2){
                    Xmax = Xmax;
                    Ymax = Ymax + len;
                    Xmin = Xmin;
                    Ymin = Ymin + 1;
                    // printf("Now1 && 24 Xmax = %d Xmin = %d Ymax = %d, Ymin = %d\n", Xmax, Xmin, Ymax, Ymin);
                    docnt(Xmax, Ymax, Xmin, Ymin);
                }
                if (lasttype == 1){
                    Xmax = Xmax;
                    Xmin = Xmin;
                    Ymax = Ymax + 1;
                    Ymin = Ymax;
                    // printf("Now2 && 11 && 25 Xmax = %d Xmin = %d Ymax = %d, Ymin = %d\n", Xmax, Xmin, Ymax, Ymin);
                    docnt(Xmax, Ymax, Xmin, Ymin);
                }
                if (lasttype == 0){
                    Xmax = Xmax;
                    Xmin = Xmin;
                    Ymax = Ymax + 1;
                    Ymin = Ymin + 1;
                    // printf("Now27 Xmax = %d Xmin = %d Ymax = %d, Ymin = %d\n", Xmax, Xmin, Ymax, Ymin);
                    docnt(Xmax, Ymax, Xmin, Ymin);
                }
            }
            if (s[i] == 'S'){
                int lasttype = type;
                type = changetype(type, 2);
                if (lasttype == 2){
                    // printf("Now1 Xmax = %d Xmin = %d Ymax = %d, Ymin = %d\n", Xmax, Xmin, Ymax, Ymin);
                    Xmax = Xmax;
                    Ymax = Ymin - 1;
                    Xmin = Xmin;
                    Ymin = Ymin - len;
                    // printf("Now8 Xmax = %d Xmin = %d Ymax = %d, Ymin = %d\n", Xmax, Xmin, Ymax, Ymin);
                    docnt(Xmax, Ymax, Xmin, Ymin);
                }
                if (lasttype == 1){
                    Xmax = Xmax;
                    Xmin = Xmin;
                    Ymin = Ymin - 1;
                    Ymax = Ymin;
                    // printf("Now2 Xmax = %d Xmin = %d Ymax = %d, Ymin = %d\n", Xmax, Xmin, Ymax, Ymin);
                    docnt(Xmax, Ymax, Xmin, Ymin);
                }
                if (lasttype == 0){
                    Xmax = Xmax;
                    Xmin = Xmin;
                    Ymax = Ymax - 1;
                    Ymin = Ymin - 1;
                    // printf("Now6 && 17 && 18Xmax = %d Xmin = %d Ymax = %d, Ymin = %d\n", Xmax, Xmin, Ymax, Ymin);
                    docnt(Xmax, Ymax, Xmin, Ymin);
                }
            }
            if (s[i] == 'W'){
                int lasttype = type;
                type = changetype(type, 3);
                if (lasttype == 2){
                    Xmax = Xmin - 1;
                    Ymax = Ymax;
                    Xmin = Xmin - len;
                    Ymin = Ymin;
                    // printf("Now12 && 14 && 16 Xmax = %d Xmin = %d Ymax = %d, Ymin = %d\n", Xmax, Xmin, Ymax, Ymin);
                    // printf("type == %d\n", type);
                    docnt(Xmax, Ymax, Xmin, Ymin);
                }
                if (lasttype == 1){
                    Xmax = Xmax - 1;
                    Xmin = Xmax;
                    Ymax = Ymax;
                    Ymin = Ymin;
                    // printf("Now9 && 10 Xmax = %d Xmin = %d Ymax = %d, Ymin = %d\n", Xmax, Xmin, Ymax, Ymin);
                    docnt(Xmax, Ymax, Xmin, Ymin);
                }
                if (lasttype == 0){
                    Xmax = Xmin - 1;
                    Xmin = Xmax;
                    Ymax = Ymax;
                    Ymin = Ymin;
                    // printf("Now13 && 15Xmax = %d Xmin = %d Ymax = %d, Ymin = %d\n", Xmax, Xmin, Ymax, Ymin);
                    docnt(Xmax, Ymax, Xmin, Ymin);
                }
            }
        }
        // printf("kkkk\n");
        if (Xmax == Xmin && Ymax == Ymin){
            printf("%d\n", Xmax);
            printf("%d\n", Ymax);
            write(Max);
            ki;
            continue;

        }
        if (Xmax == Xmin){
            fr(i, 1, len) printf("%d ", Xmax);
            ki;
            fr(i, Ymin, Ymax){
                printf("%d ", i);
            }
        }
        else{
            fr(i, Xmin, Xmax) printf("%d ", i);
            ki;
            fr(i, 1, len){
                printf("%d ", Ymax);

            }
        }
        ki;
        write(Max);
        ki;

    }

    // if (1.0 * (&Mbg - &Med) / 1024 / 1024 > 0.1) fprintf(stderr, "memo: %lf MB\n", 1.0 * (&Mbg - &Med) / 1024 / 1024);
    // else fprintf(stderr, "memo: %lf KB\n", 1.0 * (&Mbg - &Med) / 1024);
    // fprintf(stderr, "time: %lf s\n", 1.0 * (clock() - _tme) / CLOCKS_PER_SEC);
}
/*
3
2
ENEESESSESWWWN
5
WNSEWNSEWNSEWWSEN
3
NNEEESESWWNWWWWWSSEEEEENNE
*/

数字

  • 没懂,先咕掉

不会来这里

甜圈

  • 很巧的一个题啊,因为我们考虑到最终的合法状态唯一且确定,所以可以哈希....
  • 我们维护一个线段树,支持区间加和区间乘,每次更新装饰的时候,将当前的操作编号当成哈希的字符串给累乘上去,最后和合法状态比一下就行
here
#include <bits/stdc++.h>
#define LL long long
#define ULL unsigned long long 
#define Re register int
#define LD long double
#define mes(x, y) memset(x, y, sizeof(x))
#define cpt(x, y) memcpy(x, y, sizeof(x))
#define fuc(x, y) inline x y
#define fr(x, y, z)for(long long x = y; x <= z; x ++)
#define fp(x, y, z)for(long long x = y; x >= z; x --)
#define frein(x) freopen(#x ".in", "r", stdin)
#define freout(x) freopen(#x ".out", "w", stdout)
#define ki putchar('\n')
#define fk putchar(' ')
#define WMX aiaiaiai~~
#define pr pair<long long, long long>
#define mk(x, y) make_pair(x, y)
using namespace std;
namespace kiritokazuto{
    auto read = [](){
        LL x = 0;
        int f = 1;
        char c;
        while (!isdigit(c = getchar())){ if (c == '-')f = -1; }
        do{ x = (x << 1) + (x << 3) + (c ^ 48); } while (isdigit(c = getchar()));
        return x * f;
    };
    template <typename T> fuc(void, write)(T x){
        if (x < 0)putchar('-'), x = -x;
        if (x > 9)write(x / 10); putchar(x % 10 | '0');
    }
}

using namespace kiritokazuto;

bool Mbg = false;
const int maxn = 4e5 + 10, Mod = 998244353;
const int Inf = 2147483647;
LL Hash;
LL base = 233;
LL ans;
bool Med = true;
struct Seg_tree{
    ULL hash;
    ULL lazyadd, lazymul;
    LL l, r;
#define hash(rt) tr[rt].hash
#define lazya(rt) tr[rt].lazyadd
#define lazym(rt) tr[rt].lazymul
#define l(rt) tr[rt].l
#define r(rt) tr[rt].r
#define lsp(rt) (rt << 1)
#define rsp(rt) (rt << 1 | 1)
}tr[maxn << 1];
fuc(void, pushdown)(LL rt){
    hash(lsp(rt)) *= lazym(rt);
    hash(rsp(rt)) *= lazym(rt);
    lazym(lsp(rt)) *= lazym(rt);
    lazym(rsp(rt)) *= lazym(rt);
    lazya(lsp(rt)) *= lazym(rt);
    lazya(rsp(rt)) *= lazym(rt);
    hash(lsp(rt)) += lazya(rt);
    hash(rsp(rt)) += lazya(rt);
    lazya(lsp(rt)) += lazya(rt);
    lazya(rsp(rt)) += lazya(rt);
    lazya(rt) = 0;
    lazym(rt) = 1;
}
fuc(void, build) (LL rt, LL l, LL r){
    l(rt) = l;
    r(rt) = r;
    if (l == r)return;
    LL mid = (l + r) >> 1;
    build(lsp(rt), l, mid);
    build(rsp(rt), mid + 1, r);
}
fuc(void, modify)(LL rt, LL L, LL R, LL w){
    LL l = l(rt);
    LL r = r(rt);
    if (L <= l && r <= R){
        hash(rt) = hash(rt) * base + w;
        lazya(rt) *= base;
        lazym(rt) *= base;
        lazya(rt) += w;
        return;
    }
    if (lazya(rt) || lazym(rt) != 1)pushdown(rt);
    if (L <= r(lsp(rt)))modify(lsp(rt), L, R, w);
    if (R >= l(rsp(rt)))modify(rsp(rt), L, R, w);
}

fuc(void, query)(LL rt){
    if (l(rt) == r(rt)){
        ans += (Hash == hash(rt));
        return;
    }
    if (lazya(rt) || lazym(rt) != 1)pushdown(rt);
    query(lsp(rt));
    query(rsp(rt));
}

int n, x, y, w, k;
int t;
int main(){
    // frein(in);
    // freout(out2);
    n = read();
    k = read();
    t = read();
    build(1, 1, n);
    fr(i, 1, k)Hash = Hash * base + i;
    while (t--){
        x = read();
        y = read();
        w = read();
        modify(1, x, y, w);
    }
    query(1);
    write(ans);
    // if (1.0 * (&Mbg - &Med) / 1024 / 1024 > 0.1) fprintf(stderr, "memo: %lf MB\n", 1.0 * (&Mbg - &Med) / 1024 / 1024);
    // else fprintf(stderr, "memo: %lf KB\n", 1.0 * (&Mbg - &Med) / 1024);
    // fprintf(stderr, "time: %lf s\n", 1.0 * (clock() - _tme) / CLOCKS_PER_SEC);
}
/*
5 3
5
2 3 1
1 3 2
4 5 1
2 4 3
3 5 2
*/
posted @ 2022-08-21 22:13  kiritokazuto  阅读(36)  评论(0编辑  收藏  举报