ZJUT12 Day4

    科技2022-07-15  123

    ZJUT12 Day4

    1、CF 1389E Calendar Ambiguity

    tags:数学

    这题要掌握同余一个非常关键的性质: a c ≡ b c ( m o d   p ) ac\equiv bc(mod\ p) acbc(mod p)可以转化为 a ≡ b ( m o d   p g c d ( p , c ) ) a\equiv b(mod\ {p\over gcd(p, c)}) ab(mod gcd(p,c)p)

    那么分析题目,容易得到如下同余式:

    ( y − 1 ) d + x ≡ ( x − 1 ) d + y ( m o d   w ) , 1 ≤ x < y ≤ m i n ( m , d ) (y-1)d+x\equiv (x-1)d+y(mod\ w),1\le x < y \le min(m, d) (y1)d+x(x1)d+y(mod w),1x<ymin(m,d)

    移项,

    ( y − x ) ( d − 1 ) ≡ 0 ( m o d   w ) (y-x)(d-1)\equiv 0(mod\ w) (yx)(d1)0(mod w)

    这时套用最上面给出的公式得到 y − x ≡ 0 ( m o d   w g c d ( w , d − 1 ) ) y-x\equiv 0(mod \ {w\over gcd(w,d-1)}) yx0(mod gcd(w,d1)w)

    下面记 p = w g c d ( w , d − 1 ) , u p = m i n ( m , d ) p={w\over gcd(w,d-1)},up=min(m,d) p=gcd(w,d1)w,up=min(m,d)

    那么我们就是要找到在 [ 1 , u p ] [1,up] [1,up]区间内所有 y − x y-x yx p p p的倍数的整数对 ( x , y ) ( x < y ) (x,y)(x<y) (x,y)(x<y)

    最简单的想法就是枚举 y − x y-x yx,从 p p p枚举到 c n t = ⌊ u p p ⌋ cnt=\lfloor {up\over p}\rfloor cnt=pup

    那么答案就是 Σ i = 1 c n t ( u p − p i ) \Sigma_{i=1}^{cnt}(up-pi) Σi=1cnt(uppi),化简一下之后变成 c n t ∗ u p − p ( 1 + c n t ) c n t / 2 cnt*up-p(1+cnt)cnt/2 cntupp(1+cnt)cnt/2 O ( 1 ) O(1) O(1)即可求得答案。

    算上之前的 g c d gcd gcd,复杂度为 O ( l o g ( n ) ) O(log(n)) O(log(n))

    做的时候推到最后一步不会求对数了。实际上没理解到 x , y x,y x,y的取值范围是固定的,知道取值范围不变之后就非常好做了。

    #include <bits/stdc++.h> using namespace std; typedef long long ll; int main() { int t; cin >> t; while (t--) { ll m, d, w; cin >> m >> d >> w; ll p = w / __gcd(w, d - 1); ll up = min(m, d), cnt = up / p; cout << up * cnt - p * (1 + cnt) * cnt / 2 << endl; } return 0; }

    2、CF 474D MUH and Cube Walls

    tags:字符串,KMP

    实际上就是在给的 n n n个数里面找有没有出现和下面的 w w w个数一样的形状。

    那么做个差分跑一遍KMP就完了。

    注意特判 w = 1 w=1 w=1

    复杂度 O ( n + m ) O(n+m) O(n+m)

    #include <bits/stdc++.h> using namespace std; typedef long long ll; int main() { int n, w; cin >> n >> w; if (w == 1) cout << n << endl; else { vector <int> a(n), b(w); vector <int> da(n), db(w); for (int i = 0; i < n; ++i) cin >> a[i]; for (int i = 0; i < w; ++i) cin >> b[i]; for (int i = 1; i < n; ++i) da[i] = a[i] - a[i - 1]; for (int i = 1; i < w; ++i) db[i] = b[i] - b[i - 1]; vector <int> nxt(w, 0); for (int i = 2, j = 0; i < w; ++i) { while (j > 0 && db[j + 1] != db[i]) j = nxt[j]; if (db[j + 1] == db[i]) ++j; nxt[i] = j; } int cnt = 0; for (int i = 1, j = 0; i < n; ++i) { while (j > 0 && db[j + 1] != da[i]) j = nxt[j]; if (db[j + 1] == da[i]) ++j; if (j == w - 1) ++cnt, j = nxt[j]; } cout << cnt << endl; } return 0; }
    Processed: 0.012, SQL: 8