暑假集训七[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}\)值是不变的,所以两个柿子可以都合并为
- 假设我上一把死的人的位置在\(x\),即它上一把的编号为\(x\),那么我序列总共还剩下两种数字
\[ 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
*/
愿你在冷铁卷刃之前,得以窥见天光