原题是 LG-P5497 [LnOI2019SP]龟速单项式变换(SMT),原题范围
首先有个结论:n >= m ? "Yes" : "No"
即可,对于本题也就是用字符串读入,先判断一下长度再按位判断就行。
然后考虑证明这个结论,我们假装对这个序列做一个前缀和,令
我们考虑对于每一个
对于
xxxxxxxxxx
581
2
3
4
5
6
7
8
9
10
11using namespace std;
12using namespace __gnu_pbds;
13
14mt19937 rnd(random_device{}());
15int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
16bool rnddd(int x){return rndd(1, 100) <= x;}
17
18typedef unsigned int uint;
19typedef unsigned long long unll;
20typedef long long ll;
21typedef long double ld;
22
23template<typename T = int>
24inline T read(void);
25
26string N, M;
27
28// #define EXIT(f) printf("%s\n", f ? "YES" : "NO"), exit(0)
29
30int main(){
31 freopen("intriguing_t1.in", "r", stdin);
32 freopen("intriguing_t1.out", "w", stdout);
33 cin >> N >> M;
34 if(N.length() > M.length())EXIT(true);
35 if(N.length() < M.length())EXIT(false);
36 for(int i = 1; i <= (int)N.length(); ++i){
37 if(N.at(i - 1) > M.at(i - 1))EXIT(true);
38 if(N.at(i - 1) < M.at(i - 1))EXIT(false);
39 }EXIT(true);
40 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
41 return 0;
42}
43
44template<typename T>
45inline T read(void){
46 T ret(0);
47 short flag(1);
48 char c = getchar();
49 while(c != '-' && !isdigit(c))c = getchar();
50 if(c == '-')flag = -1, c = getchar();
51 while(isdigit(c)){
52 ret *= 10;
53 ret += int(c - '0');
54 c = getchar();
55 }
56 ret *= flag;
57 return ret;
58}
原创题,没原题,需要的话或许我可以在 Luogu 做一道??
emm 就是按照给的那几个公式去推一下式子就行。
然后即可
xxxxxxxxxx
601
2
3
4
5
6
7
8
9
10
11using namespace std;
12using namespace __gnu_pbds;
13
14mt19937 rnd(random_device{}());
15int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
16bool rnddd(int x){return rndd(1, 100) <= x;}
17
18typedef unsigned int uint;
19typedef unsigned long long unll;
20typedef long long ll;
21typedef long double ld;
22
23typedef __float128 f128;
24
25template<typename T = int>
26inline T read(void);
27
28int main(){
29 freopen("tomato.in", "r", stdin);
30 freopen("tomato.out", "w", stdout);
31 ll N = read<ll>(), X = read<ll>();
32 f128 tmp1 = sinf128(((f128)N + (f128)0.5) * X) * sinf128((f128)X / (f128)2);
33 f128 tmp2 = (f128)1.0 - cosf128((f128)X);
34 f128 ans = (f128)0.5 + tmp1 / tmp2;
35 printf("%.6lf\n", (double)ans);
36
37 // f128 anss(0.0);
38 // for(ll i = 0; i <= N; ++i){
39 // anss += cosf128((f128)i * (f128)X);
40 // }
41 // printf("%.6lf\n", (double)anss);
42 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
43 return 0;
44}
45
46template<typename T>
47inline T read(void){
48 T ret(0);
49 short flag(1);
50 char c = getchar();
51 while(c != '-' && !isdigit(c))c = getchar();
52 if(c == '-')flag = -1, c = getchar();
53 while(isdigit(c)){
54 ret *= 10;
55 ret += int(c - '0');
56 c = getchar();
57 }
58 ret *= flag;
59 return ret;
60}
原题 LG-P4220 [WC2018]通道。是的这是一道黑色的 WC。
虚树 + 点分治什么是虚树??我不会!
显然作为机房最弱的 tsawke 不可能会虚树分治,也不可能出虚树的题,所以这道题是爬山。
显然出题人想让我们用爬山算法解决。显然 Hack 数据也可以用奇怪的爬山通过。
(原时限 4000ms,因为是在虚拟机中测评,会慢不少,于是开了 6000ms)
考虑发现似乎这玩意是个多峰函数,于是我们可以尝试多点爬山,没必要用退火(我感觉退火应该也能过)。
考虑在时限范围内,每次随机选择一个为选择过的节点,作为起始点
然后再重新随机一个点再爬一次山,这就是多点爬山了。。。可以考虑加个卡时稳一点。然后这个东西只要你写的不是特别丑,Luogu 随便过,但是在 loj 上存在三个 Hack 数据,这样的爬山会被卡掉,当然毒瘤的 tsawke 也把这三个数据搬过来了,于是我们考虑一些新的人类智慧,在更新答案的时候像以前一样更新,然后在我们从当前的 观察数据揣摩出 Hack 数据的人的思想,我们可以想到想要让我们这个多点爬山变假的办法,基本就只能是让不同树形结构之间差距特别大,但是正解又在一个不太符合权值最大的树的单调性的位置上,这样我们就很难通过爬山去找到那个奇怪的正解的位置,于是我们考虑用一个类似枚举子集的方法去消除掉某一两棵树的贡献,只用三棵树里的一部分去作为那个多峰函数找最优解。
然后考虑在实现中,先跑几次一般的爬山,以保证对于一般数据都能通过,可以设为 exit
,这样就可以也通过 loj 上的所有数据。
和出题人斗智斗勇了属于是。
xxxxxxxxxx
1011
2
3
4
5
6
7
8
9
10
11using namespace std;
12using namespace __gnu_pbds;
13
14mt19937 rnd(random_device{}());
15int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
16bool rnddd(int x){return rndd(1, 100) <= x;}
17
18typedef unsigned int uint;
19typedef unsigned long long unll;
20typedef long long ll;
21typedef long double ld;
22
23
24
25
26
27template<typename T = int>
28inline T read(void);
29
30struct Edge{
31 Edge* nxt;
32 int to;
33 ll val;
34 OPNEW;
35}ed[MAXN * 6];
36ROPNEW(ed);
37
38int N;
39Edge* head[4][MAXN];
40ll dis[4][MAXN];
41bool vis[4][MAXN];
42bool used[MAXN];
43ll ans(-1);
44
45void dfs(int p, int ver, int fa = -1){
46 for(auto i = head[ver][p]; i; i = i->nxt){
47 if(SON == fa)continue;
48 dis[ver][SON] = dis[ver][p] + i->val;
49 dfs(SON, ver, p);
50 }
51}
52void Luangao(int f1, int f2, int f3){
53 int rt = rndd(1, N);
54 while(used[rt] && CURRENT_TIME < MAX_TIME)rt = rndd(1, N);
55 int T = 10;
56 while(T--){
57 if(used[rt])break;
58 used[rt] = true;
59 for(int i = 1; i <= 3; ++i)dis[i][rt] = 0, dfs(rt, i);
60 ll mx(0);
61 for(int i = 1; i <= N; ++i){
62 ans = max(dis[1][i] + dis[2][i] + dis[3][i], ans);
63 if(!used[i] && dis[1][i] * f1 + dis[2][i] * f2 + dis[3][i] * f3 > mx)
64 mx = dis[1][i] * f1 + dis[2][i] * f2 + dis[3][i] * f3, rt = i;
65 }
66 }
67}
68signed main(){
69 freopen("escape_from_llq.in", "r", stdin);
70 freopen("escape_from_llq.out", "w", stdout);
71 N = read();
72 for(int i = 1; i <= 3; ++i)
73 for(int j = 1; j <= N - 1; ++j){
74 int s = read(), t = read(); ll v = read<ll>();
75 head[i][s] = new Edge{head[i][s], t, v};
76 head[i][t] = new Edge{head[i][t], s, v};
77 }
78 for(int i = 1; i <= 10 && CURRENT_TIME < MAX_TIME; ++i)Luangao(1, 1, 1);
79 for(int i = 0; i <= 1; ++i)for(int j = 0; j <= 1; ++j)for(int k = 0; k <= 1; ++k)
80 if(CURRENT_TIME < MAX_TIME)Luangao(i, j, k);
81
82 printf("%lld\n", ans);
83 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
84 return 0;
85}
86
87template<typename T>
88inline T read(void){
89 T ret(0);
90 short flag(1);
91 char c = getchar();
92 while(c != '-' && !isdigit(c))c = getchar();
93 if(c == '-')flag = -1, c = getchar();
94 while(isdigit(c)){
95 ret *= 10;
96 ret += int(c - '0');
97 c = getchar();
98 }
99 ret *= flag;
100 return ret;
101}
一道新的原创题,没原题,一般的三元环计数你们都会吧??
就是把无向图的边定向,从度数大的指向度数小的,度数相同的按照编号偏序,然后从每个点枚举出点再枚举出点的出点,如果出点的出点也是起始点的出点的话那么就构成一个三元环,这样不重不漏且复杂度为
然后还有 puts("0")
即可。
然后在每有一个
然后考虑正解,显然对于三元环三个点,我们认为它们是一个有序三元组
然后这样的话显然初始时为
复杂度
xxxxxxxxxx
881
2
3
4
5
6
7
8
9
10
11using namespace std;
12using namespace __gnu_pbds;
13
14mt19937 rnd(random_device{}());
15int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
16bool rnddd(int x){return rndd(1, 100) <= x;}
17
18typedef unsigned int uint;
19typedef unsigned long long unll;
20typedef long long ll;
21typedef long double ld;
22
23
24
25
26template<typename T = int>
27inline T read(void);
28
29int N, M;
30ll fact[MAXN], inv[MAXN];
31ll qpow(ll a, ll b){
32 ll ret(1), mul(a);
33 while(b){
34 if(b & 1)ret = ret * mul % MOD;
35 b >>= 1;
36 mul = mul * mul % MOD;
37 }
38 return ret;
39}
40void Init(void){
41 fact[0] = 1;
42 for(int i = 1; i <= N; ++i)fact[i] = fact[i - 1] * i % MOD;
43 inv[N] = qpow(fact[N], MOD - 2);
44 for(int i = N - 1; i >= 0; --i)inv[i] = inv[i + 1] * (i + 1) % MOD;
45}
46ll GetC(ll n, ll m){
47 if(m > n)return 0;
48 return fact[n] * inv[m] % MOD * inv[n - m] % MOD;
49}
50ll out_pts[MAXN];
51bool changed[MAXN];
52ll ans(0);
53int main(){
54 freopen("fxxk_triatomic_ring.in", "r", stdin);
55 freopen("fxxk_triatomic_ring.out", "w", stdout);
56 N = read(), M = read();
57 Init();
58 for(int i = 1; i <= N; ++i)out_pts[i] = N - i;
59 ans = GetC(N, 3);
60 for(int i = 1; i <= N; ++i)ans = (ans - GetC(out_pts[i], 2) + MOD) % MOD;
61 printf("%lld\n", ans);
62 while(M--){
63 int s = read(), t = read();
64 if(s > t)swap(s, t);
65 ans = ((ans + GetC(out_pts[s], 2)) % MOD + GetC(out_pts[t], 2)) % MOD;
66 --out_pts[s], ++out_pts[t];
67 ans = ((ans - GetC(out_pts[s], 2) + MOD) % MOD - GetC(out_pts[t], 2) + MOD) % MOD;
68 printf("%lld\n", ans);
69 }
70 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
71 return 0;
72}
73
74template<typename T>
75inline T read(void){
76 T ret(0);
77 short flag(1);
78 char c = getchar();
79 while(c != '-' && !isdigit(c))c = getchar();
80 if(c == '-')flag = -1, c = getchar();
81 while(isdigit(c)){
82 ret *= 10;
83 ret += int(c - '0');
84 c = getchar();
85 }
86 ret *= flag;
87 return ret;
88}
emm 没什么可说的,也算是搬的题吧,从某个网页上复制下来的。
原链接 C++「阅读程序」小测验。链接里更多的题和题解都有,感兴趣可以看看。
奇怪的数据结构题,正解是莫队套 bitset
。
首先很显然,如果我们设三个区间中的交集大小为
所以那么我们所未知的需要求的也就只有 unique
以为每个数留下足够的空间,然后让相同的数,假设其离散化后的值为 bitset
套个莫队,每个 bitset
维护当前莫队区间内让每个数变得不同之后的第 bitset
的 count()
。
同时需要注意这么多 bitset
空间显然开不下,但是时间还在可以接受的范围内,所以考虑时间换空间,因为询问之间独立,所以把询问拆成三份,分别求解后输出答案即可。
最终复杂度感觉大概是 应该没算错吧,虽然对于后一项,感觉不太能过,但是确实也是 或者是我算错了)
xxxxxxxxxx
1021
2
3
4
5
6
7
8
9
10
11using namespace std;
12using namespace __gnu_pbds;
13
14mt19937 rnd(random_device{}());
15int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
16bool rnddd(int x){return rndd(1, 100) <= x;}
17
18typedef unsigned int uint;
19typedef unsigned long long unll;
20typedef long long ll;
21typedef long double ld;
22
23
24
25
26template<typename T = int>
27inline T read(void);
28
29int N, M;
30int QueryLen;
31int splitM;
32int a[MAXN];
33int cnt[MAXN], len[MAXN];
34bitset < MAXN > cur;
35bitset < MAXN > sum[MAXN / 3 + 10];
36
37struct Query{
38 int l, r;
39 int idx;
40 friend const bool operator < (const Query &x, const Query &y){
41 int xb = BLK(x.l), yb = BLK(y.l);
42 if(xb != yb)return xb < yb;
43 return xb & 1 ? x.r < y.r : x.r > y.r;
44 }
45};
46void add(int v){cur.set(v + cnt[v]++);}
47void del(int v){cur.reset(v + --cnt[v]);}
48void Solve(void){
49 memset(cnt, 0, sizeof(cnt));
50 cur.reset();
51 int tot(0);
52 vector < Query > qs;
53 while(++tot <= splitM && M--){
54 len[tot] = 0;
55 sum[tot].set();
56 int T = 3;
57 while(T--){
58 int l = read(), r = read();
59 qs.push_back(Query{l, r, tot});
60 len[tot] += r - l + 1;
61 }
62 }sort(qs.begin(), qs.end());
63 int gl(1), gr(0);
64 for(auto q : qs){
65 while(gl > q.l)add(a[--gl]);
66 while(gr < q.r)add(a[++gr]);
67 while(gl < q.l)del(a[gl++]);
68 while(gr > q.r)del(a[gr--]);
69 sum[q.idx] &= cur;
70 }--tot;
71 for(int i = 1; i <= tot; ++i)
72 printf("%d\n", len[i] - 3 * (int)sum[i].count());
73}
74int main(){
75 freopen("d0te__sturct.in", "r", stdin);
76 freopen("d0te__sturct.out", "w", stdout);
77 N = read(), M = read();
78 vector < int > arr;
79 for(int i = 1; i <= N; ++i)a[i] = read(), arr.push_back(a[i]);
80 QueryLen = sqrt(N), splitM = M / 3 + 1;
81 sort(arr.begin(), arr.end());
82 for(int i = 1; i <= N; ++i)a[i] = distance(arr.begin(), lower_bound(arr.begin(), arr.end(), a[i])) + 1;
83 Solve(), Solve(), Solve();
84 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
85 return 0;
86}
87
88template<typename T>
89inline T read(void){
90 T ret(0);
91 short flag(1);
92 char c = getchar();
93 while(c != '-' && !isdigit(c))c = getchar();
94 if(c == '-')flag = -1, c = getchar();
95 while(isdigit(c)){
96 ret *= 10;
97 ret += int(c - '0');
98 c = getchar();
99 }
100 ret *= flag;
101 return ret;
102}