【AtCoder】Dwango Programming Contest V題解

A - Thumbnail

題意簡述:給出N個數,找出N個數中和這N個數平均值絕對值最小的數c++

根據題意寫代碼便可= =算法

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define pdi pair<db,int>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define MAXN 205
#define eps 1e-8
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;char c = getchar();T f = 1;
    while(c < '0' || c > '9') {
    if(c == '-') f = -1;
    c = getchar();
    }
    while(c >= '0' && c <= '9') {
    res = res * 10 + c - '0';
    c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) {
    out(x / 10);
    }
    putchar('0' + x % 10);
}
int N,a[MAXN],s;
void Solve() {
    read(N);
    s = 0;
    for(int i = 0 ; i < N ; ++i) {read(a[i]);s += a[i];}
    int t = 0;
    for(int i = 1 ; i < N ; ++i) {
    if(abs(a[i] * N - s) < abs(a[t] * N - s)) t = i;
    }
    out(t);enter;
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Solve();
}

B - Sum AND Subarrays

題意簡述:給定N個數,子序列\([l,r]\)的美麗值定義爲\(\sum_{i = l}^{r} a_{i}\),求選出\(K\)個子序列使它們美麗值的按位與最大數組

\(\frac{N(N - 1)}{2}\)個數找出來,從大到小枚舉每一位,若是這一位是1的個數超過K個,就把這一位是0的數所有刪除,進行下一次枚舉函數

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define pdi pair<db,int>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define eps 1e-8
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;char c = getchar();T f = 1;
    while(c < '0' || c > '9') {
    if(c == '-') f = -1;
    c = getchar();
    }
    while(c >= '0' && c <= '9') {
    res = res * 10 + c - '0';
    c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) {
    out(x / 10);
    }
    putchar('0' + x % 10);
}
int N,K;
int64 a[1005],s[1005];
vector<int64> v,tmp;
void Solve() {
    read(N);read(K);
    for(int i = 1 ; i <= N ; ++i) {
    read(a[i]);
    s[i] = s[i - 1] + a[i];
    }
    for(int i = 1 ; i <= N ; ++i) {
    for(int j = i ; j <= N ; ++j) {
        v.pb(s[j] - s[i - 1]);
    }
    }
    int64 ans = 0;
    for(int i = 40 ; i >= 0 ; --i) {
    tmp.clear();
    for(auto t : v) {
        if(t >> i & 1) tmp.pb(t);
    }
    if(tmp.size() >= K) {
        ans |= (1LL << i);
        v.clear();v = tmp;
    }
    }
    out(ans);enter;
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Solve();
}

C - k-DMC

題面簡述:給出N長的字符串,求長度爲3,序列爲\(a < b < c\)知足\(s[a] = D,s[b] = M,s[c] = C\),且知足\(c - a < k\) 多組詢問kspa

從後往前維護一個單調隊列維護C,因爲咱們每次遇到一個M,會把隊列裏全部的C都+1,那咱們標記就不下放,每次新來一個C初始值設成標記的相反數便可
遇到一個D把C的座標離D超過K的所有刪除,而後隊列裏的總和便是這個D的貢獻code

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define pdi pair<db,int>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define eps 1e-8
#define MAXN 1000005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;char c = getchar();T f = 1;
    while(c < '0' || c > '9') {
    if(c == '-') f = -1;
    c = getchar();
    }
    while(c >= '0' && c <= '9') {
    res = res * 10 + c - '0';
    c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) {
    out(x / 10);
    }
    putchar('0' + x % 10);
}
char s[MAXN];
int N,Q,K;
int val[MAXN],add;
int que[MAXN],ql,qr;

void Solve() {
    read(K);
    ql = 1;qr = 0;
    add = 0;
    int64 sum = 0,ans = 0;
    for(int i = N ; i >= 1 ; --i) {
    if(s[i] == 'C') {que[++qr] = i;val[i] = -add;sum += val[i];}
    else if(s[i] == 'M') ++add;
    else if(s[i] == 'D'){
        while(ql <= qr && que[ql] - i >= K) {sum -= val[que[ql++]];}
        if(ql <= qr) {
        ans += sum + 1LL * add * (qr - ql + 1);
        }
    }
    }
    out(ans);enter;
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    read(N);
    scanf("%s",s + 1);
    read(Q);
    while(Q--) {
    Solve();
    }
}

D - Square Rotation

題意簡述:一個平面上N個點,每次能夠選一個邊長爲\(D\)的整點正方形(整點能夠有玩具也能夠沒有),每次可使坐落在整點的玩具到這個正方形順時針的下一個,這個操做能夠作任意次,要求最小化進行任意次操做後點橫縱座標差值的絕對值的最大值排序

只想出了500算法QAQ隊列

咱們考慮每一個點\((x,y)\)能夠轉成\((x % D,y % D)\),而後變成等價的一堆點,只不過須要隔\(D\)排開字符串

左下角只能是\((0,0)\)\((D - 1,D - 1)\)get

考慮一個矩形邊長爲\(aD + b\),以左下角在\((0,0)\)爲例

對於\(A_{i,j}\)表示\(x % D == i\)\(y % D == j\)的點的個數
對於\(i,j <= b\)能被覆蓋的點是\((a + 1)^2\)
對於\(i,j > b\)能被覆蓋的點是\(a^2\)
其他狀況都是\(a(a + 1)\)

顯然考慮一下,咱們的\(a\)必須是\((a + 1)^2 >= max(A_{i,j})\)
而後對於\(aD + D - 1\)必定能覆蓋全部點,因此只要考慮\(b\)就行了

咱們從(0,0)開始,計算最小的合法的\(b\),而後再枚舉剩餘的點做爲左下的點,若是能從當前的\(b\)減少則減少,不行則跳出,因爲\(b\)最多減少\(D\)次,複雜度是\(O(D^2)\)

那麼對於一個左下的點\(x,y\)怎麼判斷\(aD + b\)是否能構成一個合法的矩形呢

咱們把有值的\(A_{i,j}\)挑出來,而後把\(a^2 <A_{i,j} <= a(a + 1)\)的位置在一個二維數組裏加上1,把\(a(a + 1) < A_{i,j} <= (a + 1)^2\)的位置在另外一個二維數組裏加上1,維護成前綴和

查詢的時候看看\(a^2 <A_{i,j} <= a(a + 1)\)在沒在出現\(a^2\)的地方出現

\(a(a + 1) < A_{i,j} <= (a + 1)^2\)在沒在出現\(a^2\)\(a(a + 1)\)的地方出現

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define pdi pair<db,int>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define eps 1e-8
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;char c = getchar();T f = 1;
    while(c < '0' || c > '9') {
    if(c == '-') f = -1;
    c = getchar();
    }
    while(c >= '0' && c <= '9') {
    res = res * 10 + c - '0';
    c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) {
    out(x / 10);
    }
    putchar('0' + x % 10);
}
int cnt[1005][1005],N,D,a;
int s2[1005][1005],s3[1005][1005];
int sum2(int x1,int y1,int x2,int y2) {
    if(x1 > x2 || y1 > y2) return 0;
    ++x1,++y1,++x2,++y2;
    return s2[x2][y2] - s2[x2][y1 - 1] - s2[x1 - 1][y2] + s2[x1 - 1][y1 - 1];
}
int sum3(int x1,int y1,int x2,int y2) {
    if(x1 > x2 || y1 > y2) return 0;
    ++x1,++y1,++x2,++y2;
    
    return s3[x2][y2] - s3[x2][y1 - 1] - s3[x1 - 1][y2] + s3[x1 - 1][y1 - 1];
}
bool check2(int x,int y,int b) {
    int d1 = sum2(max(0,b + x - D + 1),max(0,b + y - D + 1),x - 1,y - 1);
    int d2 = sum2(x + b + 1,y + b + 1,D - 1,D - 1);
    int d3 = sum2(max(0,b + x - D + 1),y + b + 1,x - 1,D - 1);
    int d4 = sum2(x + b + 1,max(0,b + y - D + 1),D - 1,y - 1);
    return !d1 && !d2 && !d3 && !d4;
}
bool check3(int x,int y,int b) {
    int d1 = sum3(x + b + 1,0,D - 1,D - 1);
    int d2 = sum3(0,y + b + 1,D - 1,D - 1);
    int d3 = sum3(max(0,b + x - D + 1),0,x - 1,D - 1);
    int d4 = sum3(0,max(0,b + y - D + 1),D - 1,y - 1);
    return !d1 && !d2 && !d3 && !d4;
}
void Solve() {
    read(N);read(D);
    int x,y;
    for(int i = 1 ; i <= N ; ++i) {
    read(x);read(y);
    cnt[x % D][y % D]++;
    }
    int t = 0;
    for(int i = 0 ; i < D ; ++i) {
    for(int j = 0 ; j < D ; ++j) {
        if(cnt[i][j]) {
        t = sqrt(cnt[i][j]);
        if(t * t < cnt[i][j]) ++t;
        a = max(t - 1,a);
        }
    }
    }
    for(int i = 0 ; i < D ; ++i) {
    for(int j = 0 ; j < D ; ++j) {
        if(cnt[i][j] > a * a && cnt[i][j] <= a * (a + 1)) s2[i + 1][j + 1]++;
        else if(cnt[i][j] > a * (a + 1)) s3[i + 1][j + 1]++;
    }
    }
    for(int i = 1 ; i <= D ; ++i) {
    for(int j = 1 ; j <= D ; ++j) {
        s2[i][j] = s2[i][j] + s2[i - 1][j] + s2[i][j - 1] - s2[i - 1][j - 1];
        s3[i][j] = s3[i][j] + s3[i - 1][j] + s3[i][j - 1] - s3[i - 1][j - 1];
    }
    }
    int b;
    for(b = 0 ; b < D ; ++b) {
    if(check2(0,0,b) && check3(0,0,b)) break; 
    }
    for(int i = 0 ; i < D ; ++i) {
    for(int j = 0 ; j < D ; ++j) {
        if(!(i + j)) continue;
        while(b) {
        if(check2(i,j,b - 1) && check3(i,j,b - 1)) --b;
        else break;
        }
    }
    }
    out(a * D + b);enter;
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Solve();
}

E - Cyclic GCDs

題意簡述:給定N個數,對於它的一個置換(也就是一個排列\(P_i\),至關於\(i\)能夠走到\(P_i\),最後會造成若干環),每一個置換的價值是每一個環中最小值的乘積,求全部置換價值的最小公約數取模998244353

這題真的,過於神仙QAQ

思路清晰,結論顯然,代碼好寫,徹底就是虐我這種沒有智商的蒟蒻的

顯然咱們要把點排序,這樣的話咱們每次創建環的時候第一次遇到的點必定是要被乘起來的

咱們考慮一個\(DP[i][j]\)表示考慮了排序後的前\(i\)個點,而後建了\(j\)個環的價值(有點像第一類斯特林數啊)

而後\(b_i =DP[N][i]\)

考慮轉移有\(i * DP[i][j] \rightarrow DP[i + 1][j]\)表示把第\(i + 1\)個點放到原先存在的圈中
\(a_{i + 1} * DP[i][j] \rightarrow DP[i + 1][j + 1]\)表示把第\(i + 1\)個點自成一圈

而後用一點生成函數的小知識顯然能夠獲得
\(P_{i + 1}(x) = (a_{i + 1}x + i)P_{i}(x)\)
\(P_{0}(x) = 1\)
而後就能夠獲得\(P_{n}(x) = (a_{1}x + 0)(a_{2}x + 1)(a_{3}x + 2)...(a_{n}x + n - 1)\)

而後咱們須要開個腦洞,再證個結論

\(c(P)\)表示多項式\(P\)每一個係數的最大公約數
那麼\(c(PQ) = c(P)c(Q)\)
爲何呢,能夠這麼想,首先\(c(P)c(Q)\)必定是\(c(PQ)\)全部係數的一個約數,咱們把這些約數都除掉,如今咱們要證實\(c(P) = c(Q) = 1\)的時候,知足\(c(PQ) = 1\)
若是\(P\)\(k\)項,\(Q\)\(m\)
那麼必定能夠獲得\(PQ\)的第一項是
\(r_{k}s_{m}x^{k + m}\)
而後若是\(c(PQ)\)有一個質因子是\(p\)
那麼\(r_{k}\)\(s_{m}\)中至少有一個是\(p\)的倍數

若是\(r_{k}\)\(p\)的倍數,那麼咱們把\(r_{k}x^k\)\(P\)中刪去(由於我至關於用\(r_{k}x^{k}\)進行一次暴力卷積又對\(p\)取模)
\(s_{m}\)\(p\)的倍數同理

而後就變成了\(\prod_{i = 1}^{n} gcd(a_{i},i - 1)\)

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define pdi pair<db,int>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define eps 1e-8
#define MAXN 100005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;char c = getchar();T f = 1;
    while(c < '0' || c > '9') {
    if(c == '-') f = -1;
    c = getchar();
    }
    while(c >= '0' && c <= '9') {
    res = res * 10 + c - '0';
    c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) {
    out(x / 10);
    }
    putchar('0' + x % 10);
}
const int MOD = 998244353;
int N,A[MAXN];
int inc(int a,int b) {
    return a + b >= MOD ? a + b - MOD : a + b;
}
int mul(int a,int b) {
    return 1LL * a * b % MOD;
}
int gcd(int a,int b) {
    return b == 0 ? a : gcd(b,a % b);
}
void Solve() {
    read(N);
    for(int i = 1 ; i <= N ; ++i) read(A[i]);
    sort(A + 1,A + N + 1);
    int ans = 1;
    for(int i = 1 ; i <= N ; ++i) ans = mul(ans,gcd(A[i],i - 1));
    out(ans);enter;
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Solve();
}
相關文章
相關標籤/搜索