2018暑假多校(杭电 + 牛客)

天坑。。。

杭电

dls代码:https://ideone.com/Wo55gi

官方题解:http://bestcoder.hdu.edu.cn/blog/

2018 Multi-University Training Contest 1

1001 Maximum Multiple

打表找规律,发现只有当n是3倍数或者4倍数时才有解

而且当n%3 == 0,max(x*y*z) = (n/3) * (n/3) * (n/3)  = n^3 / 27,

当n%4 == 0, max(x*y*z) = (n/2) * (n/4) * (n/4) = n^3 / 32。

正解是解不定方程组

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head

int main() {
    int T, n;
    scanf("%d", &T);
    while(T--) {
        scanf("%d", &n);
        if(n % 3 == 0) printf("%lld\n", 1LL * n * n * n / 27);
        else if(n % 4 == 0)printf("%lld\n", 1LL * n * n * n / 32);
        else printf("-1\n");
    }
    return 0;
}
View Code

1002 Balanced Sequence

思路:贪心,先把每个括号序列用栈来使得中间的都括号都匹配,使得右括号都在左边,左括号都在右边

然后排序,我们先把右括号小于等于左括号的排在前面,然后对于右括号小于等于左括号的情况,我们按

右括号从小到大排序(因为最左边的右括号都是被浪费掉的,浪费的越小越好),然后把右括号大于左括

号的情况排在后面,对于后面这种情况,我们按左括号从大到小排序(因为最右边的左括号都是被浪费掉

的,浪费的越小越好)。

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head

const int N = 1e5 + 5;
struct node {
    int l, r;
    bool operator < (const node &t) const {
        if(r <= l && t.r > t.l) return true;
        if(r > l && t.r <= t.l) return false;
        if(r <= l && t.r <= t.l) return r < t.r;
        if(r > l && t.r > t.l) return l > t.l;
    }
}a[N];
char s[N];
int main() {
    int T, n;
    scanf("%d", &T);
    while(T--) {
        scanf("%d", &n);
        int ans = 0;
        for (int i = 0; i < n; i++) {
            scanf("%s", s);
            int l = 0, r = 0;
            for (int j = 0; j < strlen(s); j++) {
                if(s[j] == '(') l++;
                else {
                    if(l) l--, ans += 2;
                    else r++;
                }
            }
            a[i].l = l;
            a[i].r = r;
        }
        sort(a, a+n);
        int now = a[0].l;
        for (int i = 1; i < n; i++) {
            if(a[i].r >= now) {
                ans += now*2;
                now = 0;
            }
            else {
                ans += a[i].r*2;
                now -= a[i].r;
            }
            now += a[i].l;
        }
        printf("%d\n", ans);
    }
    return 0;
}
View Code

1003 Triangle Partition

1004 Distinct Values

1005 Maximum Weighted Matching

1006 Period Sequence

1007 Chiaki Sequence Revisited

思路:打表找规律,发现每个数i出现了lowbit(i)的长度次,然后二分最后a[n]的值,复杂度nlog(n)*log(n),会TLE,然后发现,a[n] -> n/2,所以将二分区间改为[n/2, n/2+100]降低复杂度

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head

const int MOD = 1e9 + 7;
const int inv = 5e8 + 4;
LL cal(LL m) {
    LL ans = 0;
    for (int i = 0; i <= 60; i++) {
        LL cnt = m / (1LL << i);
        if(cnt == 0) break;
        ans += cnt;
    }
    return ans;
}
LL sum(LL m) {
    LL ans = 0;
    for (int i = 0; i <= 60; i++) {
        LL tot = 1LL << i;
        LL cnt = m / tot;
        if(cnt == 0) break;
        LL t = ((cnt % MOD * ((cnt + 1) % MOD)) % MOD * inv) % MOD;
        t = (t * (tot % MOD) % MOD) % MOD;
        ans = (ans + t) % MOD;
    }
    return ans;
}
int main() {
    int T;
    LL n;
    scanf("%d", &T);
    while(T--) {
        scanf("%lld", &n);
        if(n <= 2) {
            printf("%lld\n", n);
            continue;
        }
        n--;
        LL l = n/2, r = (n/2)+100, m = (l + r) >> 1;
        while(l < r) {
            if(cal(m) >= n) r = m;
            else l = m + 1;
            m = (l + r) >> 1;
        }
        LL tot = cal(m-1);
        LL res = n - tot;
        LL ans = (res % MOD * (m % MOD)) % MOD;
        ans = (ans + sum(m-1) + 1) % MOD;
        ans = (ans + MOD) % MOD;
        printf("%lld\n", ans);
    }
    return 0;
}
View Code

1008 RMQ Similar Sequence

1009 Lyndon Substring

1010 Turn Off The Light

1011 Time Zone

2018 Multi-University Training Contest 2

1001 Absolute

1002 Counting Permutations

1003 Cover

思路:将度数为奇数的点两两相连,然后跑欧拉图

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head

const int N = 1e5 + 5;
vector<pii>g[N];
bool nodevs[N], edgevs[2*N];
int deg[N], cnt = 0, t, st;
vector<int>vc, vcc;
vector<int>ans[N];
void dfs(int u) {
    nodevs[u] = true;
    if(deg[u]&1) vc.pb(u), st = u;
    cnt++;
    for (int i = 0; i < g[u].size(); i++) {
        if(!nodevs[g[u][i].fi]) {
            dfs(g[u][i].fi);
        }
    }
}
void add() {
    for (int i = 0; i < vc.size(); i += 2) {
        g[vc[i]].pb({vc[i+1], t});
        g[vc[i+1]].pb({vc[i], t});
        t++;
    }
}

void DFS(int u) {
    for (int i = 0; i < g[u].size(); i++) {
        if(!edgevs[abs(g[u][i].se)]) {
            edgevs[abs(g[u][i].se)] = true;
            DFS(g[u][i].fi);
            vcc.pb(g[u][i].se);
        }
    }
}
void debug() {
    for (int i = 0; i < vcc.size(); i++) cout << vcc[i] << " ";
    cout << endl;
}
int main() {
    int n, m, u, v;
    while(~scanf("%d%d", &n, &m)) {
        mem(nodevs, false);
        mem(edgevs, false);
        mem(deg, 0);
        for (int i = 0; i <= n; i++) g[i].clear();
        for (int i = 1; i <= m; i++) {
            ans[i].clear();
            scanf("%d%d", &u, &v);
            g[u].pb({v, -i});
            g[v].pb({u, i});
            deg[u]++;
            deg[v]++;
        }
        int tot = 0;
        t = m+1;
        for (int i = 1; i <= n; i++) {
            if(!nodevs[i]) {
                cnt = 0;
                st = i;
                vc.clear();
                dfs(i);
                if(cnt == 1) continue;
                add();

                vcc.clear();
                DFS(st);
                //debug();
                int s = 0, sz = vcc.size();
                if(vc.size() > 1) {
                    while(abs(vcc[s]) <= m) {
                        s++;
                    }
                }
                else tot++;
                for (int i = s; i < s+sz; i++) {
                    if(abs(vcc[i%sz]) > m) tot++;
                    else ans[tot].pb(vcc[i%sz]);
                }

            }
        }
        printf("%d\n", tot);
        for (int i = 1; i <= tot; i++) {
            printf("%d ", ans[i].size());
            for (int j = 0; j < ans[i].size(); j++) printf("%d%c", ans[i][j], " \n"[j==ans[i].size()-1]);
        }
    }
    return 0;
}
View Code

1004 Game

思路:考虑将游戏变成初始时只有2~n,如果先手必胜的话,那么先手第一步按这样取就获胜了;如果后手必胜的话,那么先手第一步取走1就获胜了。

所以无论先后手Alice必胜。

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head

int main() {
    int n;
    while(cin >> n) puts("Yes");
    return 0;
}
View Code

1005 Hack It

思路:数论构造

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head

const int N = 3e3 + 100;
int a[N][N], p = 47;
int main() {
    fio;
    cout << 2000 << endl;
    for (int i = 0; i < p; i++) {
        for (int j = 0; j < p; j++) {
            for (int k = 0; k < p; k++) {
                a[i*p+j][k*p+(i+k*j)%p] = 1;
            }
        }
    }
    for (int i = 0; i < 2000; i++) {
        for (int j = 0; j < 2000; j++)
            printf("%d", a[i][j]);
        printf("\n");
    }
    return 0;
}
View Code

1006 Matrix

1007 Naive Operations

思路:考虑只有当ai 为 bi 倍数时i这个位置才需要被更新,于是我们倒着减bi,当bi被减成0是,我们在i这个位置+1,重新将bi设为原来的bi

判断bi为不为0用线段树维护,答案用树状数组维护,复杂为nlog(n)^2,因为调和级数的和约为n*ln(n),所以最多更新nlog(n)次

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head

const int N = 1e5 + 5;
const int INF = 0x3f3f3f3f;
int b[N];
int mn[N*4], lazy[N*4], n;
LL bit[N];
vector<int>vc;
void add(int x) {
    while(x <= n) bit[x]++, x += x&-x;
}
LL sum(int x) {
    LL ans = 0;
    while(x) ans += bit[x], x -= x&-x;
    return ans;
}
void push_up(int rt) {
    mn[rt] = min(mn[rt<<1], mn[rt<<1|1]);
}
void push_down(int rt) {
    lazy[rt<<1] += lazy[rt];
    lazy[rt<<1|1] += lazy[rt];
    mn[rt<<1] += lazy[rt];
    mn[rt<<1|1] += lazy[rt];
    lazy[rt] = 0;
}
void build(int rt, int l, int r) {
    if(l == r) {
        lazy[rt] = 0;
        mn[rt] = b[l];
        return ;
    }
    lazy[rt] = 0;
    int m = (l + r) >> 1;
    build(ls);
    build(rs);
    push_up(rt);
}
void update(int L, int R, int rt, int l, int r, int d) {
    if(L <= l && r <= R) {
        mn[rt] += d;
        if(mn[rt] == 0) {
            if(l == r) {
                vc.pb(l);
            }
            else {
                if(lazy[rt]) push_down(rt);
                int m = (l + r) >> 1;
                update(L, R, ls, d);
                update(L, R, rs, d);
            }
        }
        else lazy[rt] += d;
        return ;
    }
    if(lazy[rt]) push_down(rt);
    int m = (l+r) >> 1;
    if(L <= m)update(L, R, ls, d);
    if(R > m) update(L, R, rs, d);
    push_up(rt);
}
int query(int L, int R, int rt, int l, int r) {
    if(L <= l && r <= R) return mn[rt];
    int ans = INF;
    int m = (l+r) >> 1;
    if(L <= m) ans = min(ans, query(L, R, ls));
    if(R > m) ans = min(ans, query(L, R, rs));
    return ans;
}
int main() {
    fio;
    string s;
    int q, l, r;
    while(cin >> n >> q) {
        for (int i = 1; i <= n; i++) cin >> b[i];
        for (int i = 0; i <= n; i++) bit[i] = 0;
        build(1, 1, n);
        for (int i = 1; i <= q; i++) {
            cin >> s >> l >> r;
            if(s == "add") {
                update(l, r, 1, 1, n, -1);
                if(vc.size() > 0) {
                    //cout << vc.size() << endl;
                    for (int j = 0; j < vc.size(); j++) {
                        add(vc[j]);
                        update(vc[j], vc[j], 1, 1, n, b[vc[j]]);
                    }
                    vc.clear();
                }
            }
            else {
                cout << sum(r) - sum(l-1) << endl;
            }
        }
    }
    return 0;
}
View Code

1008 Odd Shops

1009 Segment

1010 Swaps and Inversions

思路:求个逆序数,再乘以最小花费

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head

const int N = 1e5 + 5;
vector<int>vc;
int a[N], bit[N], n;
void add(int x) {
    while(x <= n) bit[x] ++, x += x&-x;
}
int sum(int x) {
    int ans = 0;
    while(x) ans += bit[x], x -= x&-x;
    return ans;
}
int main() {
    int x, y;
    while(~ scanf("%d %d %d", &n, &x, &y)) {
        vc.clear();
        for (int i = 0; i <= n; i++) bit[i] = 0;
        for (int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
            vc.pb(a[i]);
        }
        sort(vc.begin(), vc.end());
        vc.erase(unique(vc.begin(), vc.end()), vc.end());
        for (int i = 1; i <= n; i++) {
            a[i] = lower_bound(vc.begin(), vc.end(), a[i]) - vc.begin()  +1;
        }
        LL tot = 0, ans;
        for (int i = 1; i <= n; i++) {
            tot += i - 1 - sum(a[i]);
            add(a[i]);
        }
        ans = min(x, y) * tot;
        printf("%lld\n", ans);
    }
    return 0;
}
View Code

2018 Multi-University Training Contest 3

1001 Problem A. Ascending Rating

思路:考虑到从前往后维护单调队列,维护的是单调递减的序列,与题目不符,于是我们从后往前维护单调队列,这样单调递减就变成单调递增了

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head

const int N = 1e7 + 5;
int a[N], nxt[N], tot[N];
int MOD;
int main() {
    int T, n, m, k, p, q, r;
    scanf("%d", &T);
    while(T--) {
        scanf("%d%d%d%d%d%d%d", &n, &m, &k, &p, &q, &r, &MOD);
        for (int i = 1; i <= k; i++) scanf("%d", &a[i]);
        for (int i = k+1; i <= n; i++) a[i] = (1LL * p * a[i-1] + 1LL * q * i + r) % MOD;
        LL A = 0, B = 0;
        deque<int>q;
        for (int j = n; j >= 1; j--) {
            while(!q.empty() && a[q.back()] <= a[j]) q.pop_back();
            q.push_back(j);
            while(!q.empty() && q.front() > j + m - 1) q.pop_front();
            if(j <= n-m+1) {
                //cout << a[q.front()] << " " << q.size() << endl;
                A += a[q.front()] ^ j;
                B += ((int)q.size()) ^ j;
            }
        }
        printf("%lld %lld\n", A, B);
    }
    return 0;
}
View Code

1002 Problem B. Cut The String

1003 Problem C. Dynamic Graph Matching

思路:状压dp

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head

const int MOD = 1e9 + 7;
char s[15];
int dp[2][1100][10];
int n, m;
int main() {
    int T, u, v;
    scanf("%d", &T);
    while(T--) {
        scanf("%d %d", &n, &m);
        int now = 0;
        mem(dp, 0);
        for (int i = 0; i < (1<<n); i++) dp[now][i][0] = 1;
        while(m--) {
            scanf("%s %d %d", s, &u, &v);
            now ^= 1;
            int flag;
            if(s[0] == '+') flag = 1;
            else flag = -1;
            int mx = 0;
            for (int i = 0; i < (1<<n); i++) {
                dp[now][i][0] = 1;
                for (int j = 1; j <= n/2; j++) {
                    if((i|(1<<u-1)|(1<<v-1)) == i)dp[now][i][j] = (dp[now^1][i][j] + flag * dp[now^1][i^(1<<u-1)^(1<<v-1)][j-1]) % MOD;
                    else dp[now][i][j] = dp[now^1][i][j];
                }
            }
            for (int i = 1; i <= n/2; i++) printf("%d%c", (dp[now][(1<<n)-1][i] + MOD) % MOD, " \n"[i==n/2]);
        }
    }
    return 0;
}
View Code

1004 Problem D. Euler Function

1005 Problem E. Find The Submatrix

1006 Problem F. Grab The Tree

1007 Problem G. Interstellar Travel

1008 Problem H. Monster Hunter

1009 Problem I. Random Sequence

1010 Problem J. Rectangle Radar Scanner

1011 Problem K. Transport Construction

1012 Problem L. Visual Cube

思路:构造

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
#pragma GCC optimize(2) #pragma GCC optimize(3) #p using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head

char s[100][100];
int main() {
    int T, a, b, c;
    scanf("%d", &T);
    while(T--) {
        scanf("%d%d%d", &a, &b, &c);
        int n = (c+b) * 2 + 1;
        int m = (a+b) * 2 + 1;
        for (int i = 1; i <= n; i++) {
            if(i&1){
                for (int j = 1; j <= m; j++) {
                    if(j&1)s[i][j] = '+';
                    else s[i][j] = '-';
                }
            }
            else {
                for (int j = 1; j <= m; j++) {
                    s[i][j] = '.';
                }
            }
        }

        for (int i = 1; i <= 2*b; i++) {
            for (int j = 1; j <= 2*b - i + 1; j++) {
                s[i][j] = '.';
                s[n-i+1][m-j+1] = '.';
            }
        }

        for (int i = 2*b + 2; i <= n; i += 2) {
            for (int j = 1; j <= 2*a; j += 2) {
                s[i][j] = '|';
            }
        }
        int st = 2*b+2, ed = n;
        for (int i = 2*a + 1; i <= m; i += 2) {
            for (int j = st; j <= ed; j += 2) {
                s[j][i] = '|';
                s[j][i+1] = '/';
                s[j-1][i+1] = '.';
            }
            st -= 2;
            ed -= 2;
        }

        for (int i = 2; i <= 2*b; i += 2) {
            for (int j = 2*b - i + 2; j <= 2*b - i + 2 + 2*a; j += 2) {
                s[i][j] = '/';
            }
        }
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                putchar(s[i][j]);
            }
            puts("");
        }
    }
    return 0;
}
View Code

1013 Problem M. Walking Plan

2018 Multi-University Training Contest 4

1001 Problem A. Integers Exhibition

1002 Problem B. Harvest of Apples

思路:

我们打表发现组合数的和 和 组合数的递推 是一样的:sum(n, m) = sum(n-1, m) + sum(n-1, m-1)

对N进行分块,先预处理出每i*√N行的值,然后对于每个sum(n, m)我们都能在O(√N)时间以内递推出它的值

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head

const int N = 1e5 + 5, M = 350;
const int MOD = 1e9 + 7;
int blo = sqrt(N);
vector<int>c[M];
int C[M][M], inv[N], tot = 0;
LL q_pow(LL n, LL k) {
    LL ans = 1;
    while(k) {
        if(k&1) ans = (ans * n) % MOD;
        n = (n * n) % MOD;
        k >>= 1;
    }
    return ans;
}
void init() {
    int cnt = 1;
    inv[1] = 1;
    for (int i = 2; i < N; i++) inv[i] = (MOD - MOD/i) * 1LL * inv[MOD%i] % MOD;
    for (int i = 1; i < N; i += blo) {
        c[cnt].resize(i+blo+5);
        c[cnt][0] = 1;
        LL t = 1;
        for (int j = 1; j <= i; j++) {
            tot++;
            t = (t * (i-j+1)) % MOD;
            t = (t * inv[j]) % MOD;
            c[cnt][j] = (c[cnt][j-1] + t) % MOD;
        }
        for (int j = i+1; j <= i+blo; j++) c[cnt][j] = c[cnt][i];
        cnt++;
    }
    C[0][0] = 1;
    for (int i = 1; i < M; i++) {
        for (int j = 1; j <= i; j++)
            C[i][j] = (C[i-1][j-1] + C[i-1][j]) % MOD;
    }
}
int main() {
    init();
    int T, n, m;
    scanf("%d", &T);
    while(T--) {
        scanf("%d %d", &n, &m);
        int bl = (n-1)/blo;
        int base = bl*blo + 1;
        int dis = n - base + 1;
        int l = m - dis + 1, r = m;
        LL ans = 0;
        for (int i = l, j = 1; i <= r; i++, j++) {
            if(i < 0) continue;
            ans = (ans + 1LL*C[dis][j]*c[bl+1][i]%MOD) % MOD;
        }
        printf("%lld\n", ans);
    }
    return 0;
}
View Code

1003 Problem C. Problems on a Tree

1004 Problem D. Nothing is Impossible

思路:

贪心

如果仅有 1 道题,至少有一个人做对这题需要有 错误答案个数 + 1 个人。

我们将题目按错误答案个数从小到大排序,从错误答案个数小的开始回来,看最多回答了几个问题后存在1个人全对

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head

const int N = 222;
pii a[N];
bool cmp(pii a, pii b) {
    return a.se < b.se;
}
int main() {
    int T, n, m;
    scanf("%d", &T);
    while(T--) {
        scanf("%d%d", &n, &m);
        for (int i = 0; i < n; i++) {
            scanf("%d %d", &a[i].fi, &a[i].se);
        }
        sort(a, a+n, cmp);
        int ans = 0;
        for (int i = 0; i < n; i++) {
            if(m >= 1 + a[i].se) {
                m = floor((double)m  / (1 + a[i].se));
                if(m >= 1) ans++;
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}
View Code

1005 Problem E. Matrix from Arrays

思路:我们发现当n为奇数时是以n*n为循环,当n为偶数时是以2n * 2n为循环

于是我们打好2n * 2n的表,算好前缀和,注意处理好边界

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head

const int N = 1e3 + 5;
int M[N][N], A[N];
LL sum[N][N] = {0};
int main() {
    fio;
    int T;
    cin >> T;
    while(T--) {
        int cursor = 0,  n, q, x, y, x1, y1;
        cin >> n;
        for (int i = 0; i < n; i++) cin >> A[i];
        for (int i = 0; i < 10*n; ++i) {
            for (int j = 0; j <= i; ++j) {
                M[j+1][i - j+1] = A[cursor];
                cursor = (cursor + 1) % n;
            }
        }
        /*for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                cout << M[i][j] << " ";
            }
            cout<< endl;
        }*/
        for (int i = 1; i <= 4*n; i++) {
            for (int j = 1; j <= 4*n; j++) {
                sum[i][j] = sum[i-1][j] + sum[i][j-1] - sum[i-1][j-1] + M[i][j];
            }
        }
        cin >> q;
        while(q--) {
            cin >> x >> y >> x1 >> y1;
            x++, y++, x1++, y1++;
            int h = (x1 - x + 1);
            int w = (y1 - y + 1);
            LL ans = 0;
            ans = 1LL * (w/(2*n)) * (h/(2*n)) * sum[2*n][2*n];
            int w1 = w%(2*n);
            int h1 = h%(2*n);
            int xx = x%(2*n);
            int yy = y%(2*n);
            if(xx == 0) xx += 2*n;
            if(yy == 0) yy += 2*n;
            LL s1, s2, s3;
            if(w1) {
                int xxx = xx + 2*n - 1, yyy = yy + w1 - 1;
                s1 = sum[xxx][yyy] - sum[xxx][yy-1] - sum[xx-1][yyy] + sum[xx-1][yy-1];
            }
            else s1 = 0;
            if(h1) {
                int xxx = xx + h1 - 1, yyy = yy + 2*n - 1;
                s2 = sum[xxx][yyy] - sum[xxx][yy-1] - sum[xx-1][yyy] + sum[xx-1][yy-1];
            }
            else s2 = 0;
            if(w1 && h1) {
                int xxx = xx + h1 - 1, yyy = yy + w1 - 1;
                s3 = sum[xxx][yyy] - sum[xxx][yy-1] - sum[xx-1][yyy] + sum[xx-1][yy-1];
            }
            else s3 = 0;
            ans += s1*(h/(2*n)) + s2 * (w/(2*n)) + s3;
            cout << ans << endl;
        }
    }
    return 0;
}
View Code

1006 Problem F. Travel Through Time

1007 Problem G. Depth-First Search

1008 Problem H. Eat Cards, Have Fun

1009 Problem I. Delightful Formulas

1010 Problem J. Let Sudoku Rotate

思路:搜索剪枝

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head

const int N = 100;
char s[N][N];
int g[N][N];
int t[N][N], ans;
bool vis[16];
void Rotate(int x, int y) {
    for (int i = 1, a = y; i <= 4; i++, a++) {
        for (int j = 1, b = x+3; j <= 4; j++, b--) {
            t[i][j] = g[b][a];
        }
    }
    for (int i = 1, a = x; i <= 4; i++, a++) {
        for (int j = 1, b = y; j <= 4; j++, b++) {
            g[a][b] = t[i][j];
        }
    }
}
bool check(int x, int y) {
    for (int i = 1; i <= x; i++) {
        mem(vis, false);
        for (int j = 1; j <= y; j++) {
            if(vis[g[i][j]]) return false;
            else vis[g[i][j]] = true;
        }
    }
    for (int j = 1; j <= y; j++) {
        mem(vis, false);
        for (int i = 1; i <= x; i++) {
            if(vis[g[i][j]]) return false;
            else vis[g[i][j]] = true;
        }
    }
    return true;
}
void dfs(int pos, int tot) {
    if(pos == 16) {
        ans = min(ans, tot);
        return ;
    }
    for (int i = 0; i < 4; i++) {
        if(check(pos/4*4+4, pos%4*4+4)) dfs(pos+1, tot+i);
        Rotate(pos/4*4+1, pos%4*4+1);
    }
}
int main() {
    int T;
    scanf("%d", &T);
    while(T--) {
        for (int i = 1; i <= 16; i++) {
            scanf("%s", s[i]+1);
        }
        for (int i = 1; i <= 16; i++) {
            for (int j = 1; j <= 16; j++) {
                if(isdigit(s[i][j])) g[i][j] = s[i][j] - '0';
                else g[i][j] = s[i][j] - 'A' + 10;
            }
        }
        ans = 16*3;
        dfs(0, 0);
        printf("%d\n", ans);
    }
    return 0;
}
View Code

1011 Problem K. Expression in Memories

思路:模拟

队友代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

bool check(char ch)
{
    if(ch=='+'||ch=='*') return true;
    return false;
}

int main()
{
    int n;
    scanf("%d",&n);
    while(n--)
    {
        string s;
        cin>>s;
        int len=s.size();
        int ok=1;
        int flag=0;
        for(int i=0;i<len;i++)
        {
            if(i==0&&s[i]=='0'&&!check(s[i+1])&&i+1<len)
            {
                if(s[i+1]=='?') s[i+1]='+';
                else
                {
                    ok=0;
                    break;
                }
            }
            if(check(s[i])&&s[i+1]=='0'&&!check(s[i+2])&&i+2<len)
            {
                if(s[i+2]=='?') s[i+2]='+';
                else
                {
                    ok=0;
                    break;
                }
            }
            if(s[i]=='?') s[i]='5';
            else if(check(s[i])&&check(s[i+1]))
            {
                ok=0;
                break;
            }
        }
        if(check(s[0])||check(s[len-1])) ok=0;
        if(!ok) printf("IMPOSSIBLE\n");
        else cout<<s<<endl;
    }
}
View Code

1012 Problem L. Graph Theory Homework

思路:

容易证明floor(sqrt(a)) + floor(sqrt(b)) > floor(sqrt(a+b))

所以最短路就是从1走到n

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head

const int N = 2e5 + 5;
int a[N];
int main() {
    int n, T;
    scanf("%d", &T);
    while(T--) {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
        printf("%d\n", (int)sqrt(abs(a[1] - a[n])));
    }
    return 0;
}
View Code

2018 Multi-University Training Contest 5

1001 Always Online

1002 Beautiful Now

思路:暴力搜索

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head

string s, a, b, ansmn, ansmx;
int n, k;
void dfs(int pos, int cnt) {
    if(cnt > k) return ;
    if(pos == n) {
        ansmn = min(ansmn, a);
        ansmx = max(ansmx, a);
        return ;
    }
    for (int i = pos; i < n; i++) {
        if(i == pos) {
            if(pos == 0 && a[i] == '0');
            else {
                dfs(pos+1, cnt);
            }
        }
        else {
            if(pos == 0 && a[i] == '0');
            else {
                swap(a[i], a[pos]);
                dfs(pos+1, cnt+1);
                swap(a[i], a[pos]);
            }
        }
    }
}
int main() {
    fio;
    int T;
    cin >> T;
    while(T--) {
        cin >> s >> k;
        n = s.size();
        if(k >= n-1) {
            sort(s.begin(), s.end());
            a = s;
            reverse(s.begin(), s.end());
            b = s;
            for (int i = 0; i < n; i++) {
                if(a[i] != '0') {
                    swap(a[0], a[i]);
                    break;
                }
            }
            cout << a << " " << b << endl;
        }
        else {
            a = s;
            ansmn = a;
            ansmx = a;
            dfs(0, 0);
            cout << ansmn << " " << ansmx << endl;
        }

    }
    return 0;
}
View Code

1003 Call It What You Want

1004 Daylight

1005 Everything Has Changed

思路:余弦定理

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define pf emplace_front
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stdout);
//head

int main() {
    int T, m;
    double R, x, y, r;
    scanf("%d", &T);
    while(T--) {
        scanf("%d %lf", &m, &R);
        double ans = 2 * pi * R;
        while(m--) {
            scanf("%lf %lf %lf", &x, &y, &r);
            double dd = x*x + y*y;
            if(sqrt(dd) > R + r || sqrt(dd) < R - r) continue;
            double sub = acos((R*R + dd - r*r) / (2*R*sqrt(dd)));
            double pls = acos((r*r + dd - R*R) / (2*r*sqrt(dd)));
            ans -= 2*sub*R;
            ans += 2*pls*r;
        }
        printf("%.10f\n", ans);
    }
    return 0;
}
View Code

1006 Fireflies

1007 Glad You Came

思路:线段树剪枝或者st表逆运用

线段树(700ms)

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head

const int N = 1e5 + 5;
const int MOD = 1 << 30;
int tree[N<<2], lazy[N<<2];
unsigned int X, Y, Z, t[5];
inline unsigned int f() {
    X ^= X << 11;
    X ^= X >> 4;
    X ^= X << 5;
    X ^= X >> 14;
    unsigned int W = X ^ (Y ^ Z);
    X = Y;
    Y = Z;
    Z = W;
    return Z;
}
inline void push_up(int rt) {
    tree[rt] = min(tree[rt<<1], tree[rt<<1|1]);
}
inline void push_down(int rt) {
    tree[rt<<1|1] = max(lazy[rt], tree[rt<<1|1]);
    tree[rt<<1] = max(lazy[rt], tree[rt<<1]);
    lazy[rt<<1|1] = max(lazy[rt], lazy[rt<<1|1]);
    lazy[rt<<1] = max(lazy[rt], lazy[rt<<1]);
    lazy[rt] = 0;
}
void build(int rt, int l, int r) {
    if(l == r) {
        tree[rt] = lazy[rt] = 0;
        return ;
    }
    lazy[rt] = tree[rt] = 0;
    int m = l+r >> 1;
    build(ls);
    build(rs);
}
inline void update(int L, int R, int v, int rt, int l, int r) {
    if(tree[rt] >= v)  return ;
    if(L <= l && r <= R) {
        if(tree[rt] >= v)  return ;
        else {
            if(l == r) tree[rt] = v, lazy[rt] = v;
            else {
                if(lazy[rt] < v) lazy[rt] = v;
            }
            return ;
        }
    }
    if(lazy[rt]) push_down(rt);
    int m = l+r >> 1;
    if(L <= m) update(L, R, v, ls);
    if(R > m) update(L, R, v, rs);
    push_up(rt);
}
inline int query(int p, int rt, int l, int r) {
    if(l == r) return tree[rt];
    if(lazy[rt]) push_down(rt);
    int m = l+r >> 1;
    if(p <= m) return query(p, ls);
    else return query(p, rs);
}
int main() {
    int T, n, m;
    scanf("%d", &T);
    while(T--) {
        scanf("%d %d %u %u %u", &n, &m, &X, &Y, &Z);
        build(1, 1, n);
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= 3; j++) t[j] = f();
            int l = min(t[1]%n + 1, t[2]%n + 1);
            int r = max(t[1]%n + 1, t[2]%n + 1);
            int v = t[3] % MOD;
            update(l, r, v, 1, 1, n);
        }
        LL ans = 0;
        for (int i = 1; i <= n; i++) {
            int t = query(i, 1, 1, n);
            ans ^= (1LL * i * t);
        }
        printf("%lld\n", ans);
    }
    return 0;
}
View Code

st表(2200ms)跑的比我的线段树慢多了

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head

const int N = 1e5 + 10;
const int MOD = 1 << 30;
int st[N][20], Log[N];
unsigned int X, Y, Z, t[5];
inline unsigned int f() {
    X ^= X << 11;
    X ^= X >> 4;
    X ^= X << 5;
    X ^= X >> 14;
    unsigned int W = X ^ (Y ^ Z);
    X = Y;
    Y = Z;
    Z = W;
    return Z;
}
void init(int n) {
    for (int i = 1; i <= n; i++) {
        for (int j = 0; j < 19; j++)
            st[i][j] = 0;
    }
}
void update(int l, int r, int v) {
    int k = Log[r-l+1];
    st[l][k] = max(st[l][k], v);
    st[r-(1<<k)+1][k] = max(st[r-(1<<k)+1][k], v);
}
void gao(int n) {
    for (int j = 18; j >= 1; j--) {
        for (int i = 1; i + (1<<j)-1 <= n; i++) {
            st[i][j-1] = max(st[i][j-1], st[i][j]);
            st[i+(1<<j-1)][j-1] = max(st[i+(1<<j-1)][j-1], st[i][j]);
        }
    }
}
int main() {
    int T, n, m;
    Log[2] = 1;
    for (int i = 3; i < N; i++) Log[i] = Log[i>>1] + 1;
    scanf("%d", &T);
    while(T--) {
        scanf("%d %d %u %u %u", &n, &m, &X, &Y, &Z);
        init(n);
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= 3; j++) t[j] = f();
            int l = min(t[1]%n + 1, t[2]%n + 1);
            int r = max(t[1]%n + 1, t[2]%n + 1);
            int v = t[3] % MOD;
            update(l, r, v);
        }
        gao(n);
        LL ans = 0;
        for (int i = 1; i <= n; i++) {
            int t = st[i][0];
            ans ^= (1LL * i * t);
        }
        printf("%lld\n", ans);
    }
    return 0;
}
View Code

1008 Hills And Valleys

1009 Innocence

1010 Just So You Know

1011 Kaleidoscope

1012 Lost In The Echo

2018 Multi-University Training Contest 6

1001 oval-and-rectangle

思路:积一下分就可以了,注意保留6位小数,6位之后直接舍去,不要四舍五入,而且long double不能用printf输出

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head

int main() {
    int T, a, b;
    scanf("%d", &T);
    while(T--) {
        scanf("%d %d", &a, &b);
        long double ans = (long double)2.0*(long double)a*asin((long double)1.0) + (long double)2.0*(long double)b;
        LL t = ans * 1000000;
        printf("%.6f\n", t / (double)1000000.0);
    }
    return 0;
}
View Code

1002 bookshelf

1003 Ringland

1004 Shoot Game

1005 black-and-white

1006 foam-transformation

1007 Variance-MST

1008 Rectangle Outline

1009 Werewolf

思路:首先,我们不能判断谁是村民,只能判断哪些人必定是狼,我们按类似2-sat的建边,不过是反向的,用dfs判断哪些点如果是村民,它一定会产生矛盾

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head

const int N = 1e5 + 5;
vector<int>g[N*2];
vector<int>st;
int now, n, vis[N*2];
char s[50];
int dfs(int u, bool f) {
    if(f) vis[u] = true;
    for (int i = 0; i < g[u].size(); i++) {
        if(g[u][i] == now) dfs(g[u][i], true);
        else dfs(g[u][i], f);
    }
}
int main() {
    int T, x;
    scanf("%d", &T);
    while(T--) {
        scanf("%d", &n);
        for (int i = 1; i <= 2*n; i++) g[i].clear(), vis[i] = false;
        st.clear();
        for (int i = 1; i <= n; i++) {
            scanf("%d", &x);
            scanf("%s", s);
            if(s[0] == 'v') g[x].pb(i);
            else g[x+n].pb(i), st.pb(x+n);
        }
        int ans = 0;
        for (int i = 0; i < st.size(); i++) {
            now = st[i] - n;
            dfs(st[i], false);
        }
        for (int i = 1; i <= n; i++) if(vis[i]) ans++;
        printf("0 %d\n", ans);
    }
    return 0;
}
/*
10
3
3 v
3 v
2 w
3
2 w
3 v
2 v
4
2 v
3 v
4 v
3 w

*/
View Code

1010 Chopping hands

1011 sacul

1012 Pinball

2018 Multi-University Training Contest 7

1001 Age of Moyu

1002 AraBellaC

1003 YJJ’s Stack

1004 Go to school

1005 GuGuFishtion

思路:容斥

首先,phi(n) = n * ((p1 - 1) / p1) * ((p2 - 1) / p2) * ... * ((pn - 1) / pn) 其中 pi 是n的素因子

其中, phi(1) = 1

对于a和b两个数,如果它们都有一个公共的素因子p,假设 a 中有p ^ a1,b中有 p^a2

那么考虑这个素因子的贡献

phi(a * b) = (p - 1) * p ^ (a1 + a2 - 1)                   (1) 

phi(a) * phi(b) = (p - 1) ^ 2 * p ^ (a1 + a2 - 2)      (2)

那么 (1)/ (2) = p / (p -1)

如果a 和 b 每个共同的素因子 p, 即a1 和 a2 中有一个是0

那么 (1)/ (2)= 1,没有贡献

那么只需考虑 gcd(a, b) 的贡献即可

我们要求 p1 * p2 * .. * pn / ((p1 - 1) * (p2 - 1) * ... * (pn - 1)) ,其中pi是 gcd(a, b) 的素因子

我们看一下phi(gcd(a, b))等于什么

phi(gcd(a, b)) = gcd(a, b) * ((p1 - 1) / p1) * ((p2 - 1) / p2) * ... * ((pn - 1) / pn) 其中 pi 是gcd(a, b)的素因子

所以我们要求的就等于 (1 / phi(gcd(a, b))) * gcd(a, b) = gcd(a, b) / phi(gcd(a, b)

然后问题就转换成 1 <= a <= n , 1 <= b <= m 中有多少对gcd(a, b) == k

这个可以用容斥求:

假设f[d] = d | gcd(a, b) 的个数

假设g[d] =  d == gcd(a, b) 的个数

则 g[d] = f[d] - sum(g[i*d], i >= 2) 

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define pf emplace_front
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stdout);
//head

const int N = 1e6 + 5;
bool not_pr[N];
int pr[N/5], phi[N], inv[N], f[N];
void get_phi() {
    phi[1] = 1;
    int tot = 0;
    for (int i = 2; i < N; i++) {
        if(!not_pr[i]) {
            phi[i] = i-1;
            pr[tot++] = i;
        }
        for (int j = 0; i * pr[j] < N; j++) {
            not_pr[i*pr[j]] = true;
            if(i % pr[j] == 0) {
                phi[i*pr[j]] = phi[i] * pr[j];
                break;
            }
            else phi[i*pr[j]] = phi[i] * phi[pr[j]];
        }
    }
}
int main() {
    get_phi();
    int T, n, m, mod;
    inv[1] = 1;
    scanf("%d", &T);
    while(T--) {
        scanf("%d %d %d", &n, &m, &mod);
        if(n > m) swap(n, m);
        for (int i = 2; i <= n; i++) inv[i] = (mod - mod/i) * 1LL * inv[mod%i] % mod;
        LL ans = 0;
        for (int i = n; i >= 1; i--) {
            f[i] = (1LL * (n/i) * (m/i)) % mod;
            for (int j = i+i; j <= n; j += i) f[i] = (f[i] - f[j] + mod) % mod;
            ans = (ans + 1LL * f[i] * i % mod * inv[phi[i]] % mod) % mod;
        }
        printf("%lld\n", ans);
    }
    return 0;
}
View Code

1006 Lord Li's problem

1007 Reverse Game

1008 Traffic Network in Numazu

1009 Tree

1010 Sequence

思路:我们发现有连续的一段 p/i 是一样的,而且p/i的不同个数是√p级别的,于是我们分段进行矩阵快速幂

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define pf emplace_front
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stdout);
//head

const int MOD = 1e9 + 7;
const int N = 2e5 + 5;
int dp[N];
struct Matrix {
    int a[3][3];
    void init() {
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++)
                a[i][j] = 0;
        }
    }
    void _init() {
        init();
        for (int i = 0; i < 3; i++) a[i][i] = 1;
    }
}A, B;

Matrix mul(Matrix a, Matrix b) {
    Matrix ans;
    ans.init();
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            if(a.a[i][j]) {
                for (int k = 0; k < 3; k++) ans.a[i][k] = (ans.a[i][k] + 1LL * a.a[i][j] * b.a[j][k]) % MOD;
            }
        }
    }
    return ans;
}
Matrix q_pow(Matrix a, int k) {
    Matrix ans;
    ans._init();
    if(k <= 0) return ans;
    while(k) {
        if(k&1) ans = mul(ans, a);
        a = mul(a, a);
        k >>= 1;
    }
    return ans;
}
int main() {
    int T, a, b, c, d, p, n;
    scanf("%d", &T);
    A.init();
    A.a[0][2] = 1;
    A.a[1][0] = 1;
    A.a[2][2] = 1;
    B.init();
    while(T--) {
        scanf("%d %d %d %d %d %d", &a, &b, &c, &d, &p, &n);
        dp[1] = a;
        dp[2] = b;
        if(n <= 50000) {
            for (int i = 3; i <= n; i++) dp[i] = (1LL * c * dp[i-2] + 1LL * d *dp[i-1] + p/i) % MOD;
            printf("%d\n", dp[n]);
        }
        else {
            A.a[0][0] = d;
            A.a[0][1] = c;
            B.a[0][0] = dp[2];
            B.a[1][0] = dp[1];
            for (int i = 3; i <= n;) {
                int j;
                if(p/i == 0) j = n;
                else j = min(n, p/(p/i));
                B.a[2][0] = p/i;
                B = mul(q_pow(A, j-i+1), B);
                i = j+1;
            }
            printf("%d\n", B.a[0][0]);
        }
    }
    return 0;
}
View Code

1011 Swordsman

2018 Multi-University Training Contest 8

1001 Character Encoding

思路:生成函数+广义二项式定理

队友代码:

#include<bits/stdc++.h>
using namespace std;
const long long mod=998244353;
long long POW(long long x,long long n){
    long long re=1,base=x;
    while(n){
        if(n&1)(re*=base)%=mod;
        (base*=base)%=mod;
        n>>=1;
    }
    return re;
}
long long inv[200010],fac[200010],nfac[200010],ninv[200010];
 
void getFac(){
    fac[0]=1,nfac[0]=1;
    for(int i=1;i<=200000;i++)fac[i]=fac[i-1]*i%mod;
    for(int i=1;i<=200000;i++)nfac[i]=(mod+nfac[i-1]*(-i)%mod)%mod;
    inv[200000]=POW(fac[200000],mod-2);
    ninv[200000]=POW(nfac[200000],mod-2);
    for(int i=200000;i>=1;i--)inv[i-1]=inv[i]*i%mod,ninv[i-1]=(mod+ninv[i]*(-i)%mod)%mod;
}
long long C(long long n,long long m){
    if(m<0)return 0;
    long long re=inv[m];
//    re=inv[m]*(n>0?fac[n]:nfac[-n])%mod*(n-m>0?inv[n-m]:ninv[m-n])%mod;
    
    if(n>=0&&m>=0)re=re*fac[n]%mod*inv[n-m]%mod;
    else if(n<0&&m>=0)re=re*ninv[-n-1]%mod*nfac[m-n-1]%mod;
    
//    for(int i=0;i<m;i++)re=(re*(n-i)%mod+mod)%mod;
//    for(int i=1;i<=m;i++)re=(re*(POW(i,mod-2))%mod+mod)%mod;
    return re;
}
long long sign(long long x){
    if(x&1)return -1;
    else return 1;
}
int main(){
    int T;
    getFac();
    cin>>T;
    long long n,m,k;
    for(int t=1;t<=T;t++){
        scanf("%lld%lld%lld",&n,&m,&k);
        long long ans=0;
        for(long long i=0;i<=m;i++){
            (ans+=C(m,i)*sign(m-i)*C(-m,k-i*n)*sign(-m-k+i*n)%mod+mod)%=mod;
        }
        cout<<(ans+mod)%mod<<endl;
    }
    return 0;
}
View Code

1002 Pizza Hub

1003 City Development

1004 Parentheses Matrix

思路:首先,当n和m都是奇数时一个goodness都没有,随便构造,其次,当n和m中有一个是偶数时,所有行或者所有列都是构造成匹配的

当n和m都为偶数时(假设n > m),可以这样构造:

我们发现这样构造的的goodness是 n + (m - 2) / 2

我们还可以这样构造(牺牲最上面一行和最下面一行以及最左边一列和最右边一列来成全中间的所有行和列):

这样构造的goodness是 n + m - 4

解个不等式: n + (m - 2) / 2 >= n + m - 4

得: m <= 6

综上所述:

当min(n, m) <= 6 时,采用第一种构造;当min(n, m) > 6时,采用第二种构造

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head

const int N = 222;
char s[N][N];
int main() {
    int T, n, m;
    scanf("%d", &T);
    while(T--) {
        scanf("%d %d", &n, &m);
        if(n%2 == 0 && m%2 == 0 && min(n, m) > 6) {
            for (int i = 1; i <= m; i++) s[1][i] = '(', s[n][i] = ')';
            for (int i = 2; i < n; i++) {
                if((i-1)&1) {
                    for(int j = 1; j <= m; j++) {
                        if(j&1) s[i][j] = '(';
                        else s[i][j] = ')';
                    }
                }
                else {
                    s[i][1] = '(';
                    s[i][m] = ')';
                    for (int j = 2; j < m; j++) {
                        if((j-1)&1) s[i][j] = '(';
                        else s[i][j] = ')';
                    }
                }
            }
            for (int i = 1; i <= n; i++) {
                for (int j = 1; j <= m; j++) {
                    putchar(s[i][j]);
                }
                puts("");
            }
            continue;
        }
        if(n < m) {
            if(n%2 == 0) {
                for (int j = 1; j <= m; j++) {
                    if(j&1) {
                        s[1][j] = '(';
                        s[n][j] = ')';
                        for (int i = 2; i < n; i++) {
                            if((i-1)&1) s[i][j] = '(';
                            else s[i][j] = ')';
                        }
                    }
                    else {
                        for (int i = 1; i <= n; i++) {
                            if(i&1) s[i][j] = '(';
                            else s[i][j] = ')';
                        }
                    }
                }
            }
            else if(m%2 == 0) {
                for (int i = 1; i <= n; i++) {
                    if(i&1) {
                        s[i][1] = '(';
                        s[i][m] = ')';
                        for (int j = 2; j < m; j++) {
                            if((j-1)&1) s[i][j] = '(';
                            else s[i][j] = ')';
                        }
                    }
                    else {
                        for (int j = 1; j <= m; j++) {
                            if(j&1) s[i][j] = '(';
                            else s[i][j] = ')';
                        }
                    }
                }
            }
            else {
                for (int i = 1; i <= n; i++) {
                    for (int j = 1; j <= m; j++)
                        s[i][j] = '(';
                }
            }
        }
        else {
            if(m%2 == 0) {
                for (int i = 1; i <= n; i++) {
                    if(i&1) {
                        s[i][1] = '(';
                        s[i][m] = ')';
                        for (int j = 2; j < m; j++) {
                            if((j-1)&1) s[i][j] = '(';
                            else s[i][j] = ')';
                        }
                    }
                    else {
                        for (int j = 1; j <= m; j++) {
                            if(j&1) s[i][j] = '(';
                            else s[i][j] = ')';
                        }
                    }
                }
            }
            else if(n%2 == 0) {
                for (int j = 1; j <= m; j++) {
                    if(j&1) {
                        s[1][j] = '(';
                        s[n][j] = ')';
                        for (int i = 2; i < n; i++) {
                            if((i-1)&1) s[i][j] = '(';
                            else s[i][j] = ')';
                        }
                    }
                    else {
                        for (int i = 1; i <= n; i++) {
                            if(i&1) s[i][j] = '(';
                            else s[i][j] = ')';
                        }
                    }
                }
            }
            else {
                for (int i = 1; i <= n; i++) {
                    for (int j = 1; j <= m; j++)
                        s[i][j] = '(';
                }
            }
        }
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                putchar(s[i][j]);
            }
            puts("");
        }
    }
    return 0;
}
View Code

1005 Magic Square

1006 Boolean 3-Array

1007 Card Game

1008 K-Similar Strings

1009 Make ZYB Happy

1010 Taotao Picks Apples

思路:先用二分+st表采用dp求出每个位置往后的递增序列长度(对于dp[i],二分找到后面第一个比a[i]大的数a[j],然后dp[i] = dp[j] + 1)

再预处理出原序列到当前位置的递增序列的值以及长度,然后对于每个询问p和q,考虑将a[p]改变成q的影响来求答案

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head

const int N = 1e5 + 10;
const int INF = 0x7f7f7f7f;
int a[N], dp[N], mx[N][20], v[N], pre[N], Log[N];
void init(int n) {
    for (int i = 0; i < 19; i++) {
        for (int j = 1; j + (1<<i) - 1 <= n; j++) {
            if(i == 0) mx[j][i] = a[j];
            else mx[j][i] = max(mx[j][i-1], mx[j+(1<<i-1)][i-1]);
        }
    }
}
int query(int l, int r) {
    int k = Log[r-l+1];
    return max(mx[l][k], mx[r-(1<<k)+1][k]);
}
int main() {
    int T, n, M, p, q;
    scanf("%d", &T);
    Log[2] = 1;
    for (int i = 3; i < N; i++) Log[i] = Log[i>>1] + 1;
    while(T--) {
        scanf("%d%d", &n, &M);
        for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
        a[n+1] = INF;
        dp[n+1] = 0;
        init(n);
        for (int i = n; i >= 1; i--) {
            int l = i+1, r = n+1, m = l+r >> 1;
            while(l < r) {
                if(query(i+1, m) > a[i]) r = m;
                else l = m+1;
                m = l+r >> 1;
            }
            dp[i] = dp[m] + 1;
        }
        v[0] = 0, pre[0] = 0;
        for (int i = 1; i <= n; i++) {
            if(a[i] > v[i-1]) {
                v[i] = a[i];
                pre[i] = pre[i-1] + 1;
            }
            else v[i]  = v[i-1], pre[i] = pre[i-1];
        }
        for (int i = 0; i < M; i++) {
            scanf("%d %d", &p, &q);
            int ans = pre[p-1];
            if(q > v[p-1]) {
                ans++;
                int l = p+1, r = n+1, m = l+r >> 1;
                while(l < r) {
                    if(query(p+1, m) > q) r = m;
                    else l = m+1;
                    m = l+r >> 1;
                }
                ans += dp[m];
            }
            else {
                int l = p+1, r = n+1, m = l+r >> 1;
                while(l < r) {
                    if(query(p+1, m) > v[p-1]) r = m;
                    else l = m+1;
                    m = l+r >> 1;
                }
                ans += dp[m];
            }
            printf("%d\n", ans);
        }
    }
    return 0;
}
View Code

1011 Pop the Balloons

1012 From ICPC to ACM

2018 Multi-University Training Contest 9

1001 Rikka with Nash Equilibrium

思路:dp,用滚动数组优化一下空间

从大到小填数字,dp[now][i][j]表示当前填了now个数字,选中了i行和j列的方案数

具体转移看代码:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head

const int N = 85;
int mod;
int dp[2][N][N];
int main() {
    int T, n, m;
    scanf("%d", &T);
    while(T--) {
        scanf("%d %d %d", &n, &m, &mod);
        for (int i = 0; i < 2; i++) {
            for (int j = 0; j <= n; j++) {
                for (int k = 0; k <= m; k++)
                    dp[i][j][k] = 0;
            }
        }
        int now = 0;
        dp[now][1][1] = (n*m) % mod;
        for (int i = 2; i <= n*m; i++) {
            for (int j = 1; j <= n; j++) {
                for (int k = 1; k <= m; k++) {
                    dp[now^1][j][k] = 0;
                    dp[now^1][j][k] = (dp[now^1][j][k] + 1LL * k * (n - j + 1) * dp[now][j-1][k] + 1LL * j * (m - k + 1) * dp[now][j][k-1]) % mod;
                    dp[now^1][j][k] = (dp[now^1][j][k] + (j*k - (i-1)) * 1LL * dp[now][j][k]) % mod;
                }
            }
            now ^= 1;
        }
        printf("%lld\n", dp[now][n][m] % mod);
    }
    return 0;
}
View Code

1002 Rikka with Seam

1003 Rikka with APSP

1004 Rikka with Stone-Paper-Scissors

思路:公式 (a' * (c - b) + b' * (a - c) + c' * (b - a)) / (a + b + c)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll>pii;
pii getAns(ll a,ll b,ll c,ll aa,ll bb,ll cc){
    ll fi=aa*(c-b)+bb*(a-c)+cc*(b-a);
    ll se=a+b+c;
    return pii(fi,se);
}
int main(){
    long long T;
    cin>>T;
    long long a,b,c,aa,bb,cc;
    for(int t=1;t<=T;t++){
        cin>>a>>b>>c>>aa>>bb>>cc;
        pii ans=getAns(a,b,c,aa,bb,cc);
        ll gcd= __gcd(abs(ans.first),ans.second);
        if(gcd==ans.second){
            cout<<ans.first/gcd<<endl;
        }
        else cout<<ans.first/gcd<<'/'<<ans.second/gcd<<endl;
    }
    return 0;
}
View Code

1005 Rikka with Rain

1006 Rikka with Spanning Tree

1007 Rikka with Treasure

1008 Rikka with Line Graph

1009 Rikka with Bubble Sort

1010 Rikka with Time Complexity

1011 Rikka with Badminton

思路:

容斥推出公式:2^a * ((b+d+1)* 2^c + 2^b - (b+1))

一个不行的加起来,减去两个都不行的

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head

const int MOD = 998244353;
LL q_pow(LL n, LL k) {
    LL ans = 1;
    while(k) {
        if(k&1) ans = (ans * n) % MOD;
        n = (n * n) % MOD;
        k >>= 1;
    }
    return ans;
}
int main() {
    int T, a, b, c, d;;
    scanf("%d", &T);
    while(T--) {
        scanf("%d %d %d %d", &a, &b, &c, &d);
        LL ans = q_pow(2, a) * 1LL *  ( q_pow(2, c) * 1LL *(b + d + 1) % MOD + q_pow(2, b) - (1+b) + MOD) % MOD;
        printf("%lld\n", ans);
    }
    return 0;
}
View Code

 2018 Multi-University Training Contest 10

1001 Problem A.Alkane

1002 Problem B. Beads

1003 Problem C. Calculate

1004 Problem D. Permutation

1005 Problem E. TeaTree

思路:bitset瞎搞

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head

const int N = 1e5 + 5;
vector<int>g[N];
vector<int>f[N];
int v[N], ans[N];
void init() {
    for (int i = 1; i < N; i++) {
        for (int j = i; j < N; j += i) {
            f[j].pb(i);
        }
    }
}
bitset<N> dfs(int u) {
    bitset<N> res;
    for (int t : f[v[u]]) res.set(N - t);
    ans[u] = -1;
    for (int v : g[u]) {
        bitset<N> t = dfs(v);
        ans[u] = max(ans[u], (int)(N - (res&t)._Find_first()));
        res |= t;
    }
    return res;
}
int main() {
    int n, u;
    init();
    scanf("%d", &n);
    for (int i = 2; i <= n; i++) {
        scanf("%d", &u);
        g[u].pb(i);
    }
    for (int i = 1; i <= n; i++) scanf("%d", &v[i]);
    dfs(1);
    for (int i = 1; i <= n; i++) {
        if(ans[i] <= 0) printf("-1\n");
        else printf("%d\n", ans[i]);
    }
    return 0;
}
View Code

1006 Problem F. NewNippori

1007 Problem G. Cyclic

思路:打表找规律

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353;
ll a[100005];
void get_num()
{
    a[1]=1;
    a[2]=0;
    a[3]=1;
    a[4]=1;
    a[5]=8;
    a[6]=36;
    for(ll i=7;i<=100000;i++)
    {
        a[i]=(((i-2)*a[i-1])%mod+((i-1)*a[i-2])%mod+((i&1)?1:-1))%mod;
    }
//    for(int i=1;i<=20;i++) cout<<a[i]<<endl;
}
int main()
{
    int t;
    scanf("%d",&t);
    get_num();
    while(t--)
    {
        int n;
        scanf("%d",&n);
//        n-=4;
        cout<<a[n]<<endl;
    }
}
View Code

1008 Problem H. Pow

思路:高精度,用pow(2,n)也可以,跟计算机存储浮点数存储方式有关

double指数位可以从- 2^10 到 2^10 - 1

import java.util.*;
import java.lang.*;
import java.io.*;
import java.math.*;

/* Name of the class has to be "Main" only if the class is public. */
public class Main
{
    public static void main (String[] args) 
    {
        Scanner reader = new Scanner(System.in);
        int T, n;
        T = reader.nextInt();
        while(T != 0) {
            T--;
            n = reader.nextInt();
            BigInteger ans = new BigInteger("1");
            for (int i = 1; i <= n; i++) {
                ans = ans.multiply(BigInteger.valueOf(2));
            }
            System.out.println(ans);
        }
        // your code goes here
    }
}
View Code

1009 Problem I. Count

思路:打表找规律,与欧拉函数有关

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head

const int N = 20000100;
int phi[N], prime[N/5];
LL ans[N];
bool not_prime[N];
void Euler()
{
    phi[1]=1;
    int k=0;
    for(int i=2;i< N;i++)
    {
        if(!not_prime[i])
        {
            phi[i]=i-1;
            prime[k++]=i;
        }
        for(int j=0; i*prime[j] < N; j++)
        {
            not_prime[i*prime[j]]=true;
            if(i%prime[j]==0)
            {
                phi[i*prime[j]]=phi[i]*prime[j];
                break;
            }
            else phi[i*prime[j]]=phi[i]*phi[prime[j]];
        }
    }
}
int main() {
    Euler();
    ans[0] = 0;
    for (int i = 1; i < N; i++) {
        if(i&1) ans[i] = ans[i-1] + phi[i]/2;
        else ans[i] = ans[i-1] + phi[i];
    }
    int T, n;
    scanf("%d", &T);
    while(T--) {
        scanf("%d", &n);
        printf("%lld\n", ans[n]);
    }
    return 0;
}
View Code

1010 Problem J. CSGO

思路:用二进制枚举绝对值去掉后每个数前面的加减号。

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head

const int N = 1e5 + 10;
const LL INF = 0x3f3f3f3f3f3f3f3f;
struct node {
    int s;
    int x[5];
}a[N], b[N];
bool cmp1(node a, node b) {
    return a.s < b.s;
}
bool cmp2(node a, node b) {
    return a.x[0] < b.x[0];
}
bool cmp3(node a, node b) {
    return a.x[1] < b.x[1];
}
bool cmp4(node a, node b) {
    return a.x[2] < b.x[2];
}
bool cmp5(node a, node b) {
    return a.x[3] < b.x[3];
}
bool cmp6(node a, node b) {
    return a.x[4] < b.x[4];
}
LL mxa[50], mna[50], mxb[50], mnb[50];
int main() {
    int T;
    scanf("%d", &T);
    while(T--) {
        int n, m, k;
        scanf("%d %d %d", &n, &m, &k);
        for (int i = 0; i < (1<<k); i++) mxa[i] = mxb[i] = -INF, mna[i] = mnb[i] = INF;
        for (int i = 1; i <= n; i++) {
            scanf("%d", &a[i].s);
            for (int j = 0; j < k; j++) {
                scanf("%d", &a[i].x[j]);
            }
            for (int j = 0; j < (1<<k); j++) {
                LL t = a[i].s;
                for (int l = 0; l < k; l++) {
                    if(j & (1<<l)) t += a[i].x[l];
                    else t -= a[i].x[l];
                }
                mna[j] = min(mna[j], t);
                mxa[j] = max(mxa[j], t);
            }
        }
        for (int i = 1; i <= m; i++) {
            scanf("%d", &b[i].s);
            for (int j = 0; j < k; j++) {
                scanf("%d", &b[i].x[j]);
            }
            for (int j = 0; j < (1<<k); j++) {
                LL t = b[i].s;
                for (int l = 0; l < k; l++) {
                    if(j & (1<<l)) t += b[i].x[l];
                    else t -= b[i].x[l];
                }
                mnb[j] = min(mnb[j], t);
                mxb[j] = max(mxb[j], t);
            }
        }
        int up = (1<<k) - 1;
        LL ans = 0;
        for (int j = 0; j < (1<<k); j++) {
            ans = max(ans, mna[j] + mnb[up^j]);
            ans = max(ans, mna[j] + mxb[up^j]);
            ans = max(ans, mxa[j] + mnb[up^j]);
            ans = max(ans, mxa[j] + mxb[up^j]);
            //cout << j << " " << ans << endl;
        }
        printf("%lld\n", ans);
    }
    return 0;
}
/*
100
5 5 1
3 3
-5 0
0 -5
5 0
0 5

2 -4
5 0
0 5
-5 0
0 -5

*/
View Code

1011 Problem K. Pow2

1012 Problem L.Videos

牛客

牛客网暑期ACM多校训练营(第一场)

Monotonic Matrix

思路:找规律

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head
 
const int N = 2e3 + 10;
const int MOD = 1e9 + 7;
LL dp[N][N], t[2*N][2*N];
LL q_pow(LL n, LL k) {
     LL ans = 1;
     while(k) {
        if(k&1) ans = (ans * n) % MOD;
        n = (n * n) % MOD;
        k >>= 1;
     }
     return ans;
}
int main() {
    t[1][1] = 3;
    for (int i = 2; i < 2*N; i++) t[1][i] = (t[1][i-1] + i+1) % MOD;
    for (int i = 2; i < N; i++) {
        for (int j = 1; j < N; j++) {
            if(j == 1) t[i][j] = t[j][i];
            else {
                t[i][j] = (t[i][j-1] * t[1][i+j-1] % MOD * q_pow(t[1][j-1], MOD-2)) % MOD;
            }
        }
    }
    int n, m;
    while(~
    scanf("%d %d", &n, &m)) {
        printf("%lld\n", t[n][m]);
    }
    return 0;
}
View Code

Symmetric Matrix

Fluorescent 2

Two Graphs

思路:状态压缩

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head
 
const int N = 100;
pii e1[N], e2[N];
int n, m1, m2, ans;
int vis[10][10], cnt[10], vs[10][10], a[10], t[10][10];
map<int, int>mp;
int main() {
    while( ~ scanf("%d %d %d", &n, &m1, &m2)) {
        mem(vs, 0);
        mem(cnt, 0);
        for (int i = 0; i < m1; i++) {
            scanf("%d %d", &e1[i].fi, &e1[i].se);
            if(e1[i].fi > e1[i].se) swap(e1[i].fi, e1[i].se);
            vs[e1[i].fi][e1[i].se] = 1;
        }
        mem(vis, 0);
        for (int i = 0; i < m2; i++) {
            scanf("%d %d", &e2[i].fi, &e2[i].se);
            if(e2[i].fi > e2[i].se) swap(e2[i].fi, e2[i].se);
            vis[e2[i].fi][e2[i].se] = 1;
        }
 
        int sta = 0;
        for (int i = 1; i <= n; i++) {
            for (int j = i + 1; j <= n; j++) {
                sta = sta * 2 + vis[i][j];
            }
        }
        int ans = 0;
        mp.clear();
        for (int i = 1; i <= n; i++) a[i] = i;
        do {
            int s = 0;
            for (int i = 1; i <= n; i++) {
                for (int j = i+1; j <= n; j++) {
                    t[i][j] = 0;
                }
            }
            for (int i = 1; i <= n; i++) {
                for (int j = i+1; j <= n; j++) {
                    if(vs[i][j]) {
                        if(a[i] < a[j]) t[a[i]][a[j]] = 1;
                        else t[a[j]][a[i]] = 1;
                    }
                }
            }
            for (int i = 1; i <= n; i++) {
                for (int j = i+1; j <= n; j++) {
                    s = s * 2 + t[i][j];
                }
            }
            mp[s]++;
        }while(next_permutation(a+1, a+1+n));
        for (auto it = mp.begin(); it != mp.end(); it++) {
            int s = it -> fi;
            if((s & sta) == s) ans++;
        }
        printf("%d\n", ans);
    }
    return 0;
}
/*
3 1 2
1 3
1 2
1 3
4 2 3
1 2
1 3
4 1
4 2
4 3
*/
View Code

Removal

Sum of Maximum

Steiner Tree

Longest Path

Substring

Different Integers

思路:莫队

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head
 
const int N = 1e5 + 5;
int a[N], cnt[N], blo, ans, res[N];
struct edge {
    int l, r, bl, id;
    bool operator < (const edge & t) const {
        if(bl == t.bl) return r < t.r;
        else return l < t.l;
    }
}Q[N];
void add(int x) {
    if(!cnt[a[x]]) ans++;
    cnt[a[x]]++;
}
void ded(int x) {
    cnt[a[x]]--;
    if(!cnt[a[x]]) ans--;
}
int main() {
    int n, q;
    while( ~scanf("%d %d", &n, &q)) {
        blo = sqrt(n);
        mem(cnt, 0);
        ans = 0;
        for (int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
            if(!cnt[a[i]]) ans++;
            cnt[a[i]]++;
        }
        for (int i = 1; i <= q; i++)  {
            scanf("%d %d", &Q[i].l, &Q[i].r);
            Q[i].id = i;
            Q[i].l ++;
            Q[i].r --;
            Q[i].bl = (Q[i].l - 1) / blo;
        }
        sort(Q+1, Q+1+q);
        int i = 1, l, r;
        for (i = 1; i <= q; i++) {
            if(Q[i].l <= Q[i].r) {
                l = Q[i].l+1;
                r = Q[i].l;
                break;
            }
            else res[Q[i].id] = ans;
        }
        for (; i <= q; i++) {
            while(l < Q[i].l) add(l++);
            while(l > Q[i].l) ded(--l);
            while(r < Q[i].r) ded(++r);
            while(r > Q[i].r) add(r--);
            //cout << l << " " << r << " " << ans << endl;
            res[Q[i].id] = ans;
        }
        for (int i = 1; i <= q; i++) printf("%d\n", res[i]);
    }
    return 0;
}
/*
10 10
1 2 3 4 5 6 7 8 9 10
4 5
5 6
6 7
8 9
4 6
4 7
4 8
4 9
4 10
4 10
*/
View Code

牛客网暑期ACM多校训练营(第二场)

run

思路:dp

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head
 
const int N = 1e5 + 5;
const int MOD = 1e9 + 7;
LL dp[N][2], sum[N];
int main() {
    int q, k, l, r;
    scanf("%d %d", &q, &k);
    dp[0][0] = 1;
    for (int i = 1; i < N; i++) {
        dp[i][0] += dp[i-1][0] + dp[i-1][1];
        dp[i][0] %= MOD;
        if(i - k >= 0) dp[i][1] += dp[i-k][0];
        dp[i][1] %= MOD;
    }
    sum[0] = 1;
    for (int i = 1; i < N; i++) {
        sum[i] = (sum[i-1] + dp[i][0] + dp[i][1]) % MOD;
    }
    while(q--) {
        scanf("%d %d", &l, &r);
        printf("%lld\n", ((sum[r] - sum[l-1]) % MOD + MOD) % MOD);
    }
    return 0;
}
View Code

discount

message

money

思路:贪心,每次找连续上升的一段

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head
 
const int N = 1e5 + 5;
int a[N];
int main() {
    int T, n;
    scanf("%d", &T);
    while(T--) {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
        int pre = 1, cnt = 0, now = 0;
        LL ans = 0;
        for (int i = 2; i <= n; i++) {
            if(a[i] >= a[i-1]) {
                now = i;
            }
            else {
                if(now > pre && a[now] != a[pre]){
                    ans += a[now] - a[pre];
                    cnt += 2;
                }
                pre = i;
            }
        }
        if(now > pre && a[now] != a[pre]) ans += a[now] - a[pre], cnt += 2;
        printf("%lld %d\n", ans, cnt);
    }
    return 0;
}
View Code

tree

trade

transform

思路:二分

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head
 
const int N = 5e5 + 5;
LL pren[N], pres[N], sufn[N], sufs[N];
int n;
LL T;
struct node {
    int x, a;
    bool operator < (const node & t) const {
        return x < t.x;
    }
}a[N];
LL get_pres(int l, int r) {
    return pres[r] - pres[l] - (a[r].x - a[l].x) * pren[l];
}
LL get_sufs(int l, int r) {
    return sufs[l] - sufs[r] - (a[r].x - a[l].x) * sufn[r];
}
bool check(LL m) {
    int mid = 0, r = 0;
    LL cnt1 = (m+1)/2;
    for (int i = 1; i <= n; i++) {
        while(mid <= n && pren[mid] - pren[i-1] < cnt1) mid++;
        if(mid > n) break;
        while(r <= n && pren[r] - pren[i-1] < m) r++;
        if(r > n) break;
        if((get_pres(i-1, mid) + get_sufs(mid, r+1) - (pren[r] - pren[i-1] - m) * (a[r].x - a[mid].x)) * 2 <= T) return true;
        if((get_pres(i-1, mid) + get_sufs(mid, r+1) - (pren[r] - pren[i-1] - m) * (a[i].x - a[mid].x)) * 2 <= T) return true;
    }
//    mid = r = n;
//    for (int i = n; i >= 1; i--) {
//        while(mid >= 1 && sufn[mid] - sufn[i+1] < cnt1) mid--;
//        if(mid < 1) break;
//        while(r >= 1 && sufn[r] - sufn[i+1] < m) r--;
//        if(r < 1) break;
//        if((get_pres(r-1, mid) + get_sufs(mid, i+1) - (pren[i] - pren[r-1] - m) * (a[mid].x - a[r].x)) * 2 <= T) return true;
//        if((get_pres(r-1, mid) + get_sufs(mid, i+1) - (m - pren[i] + pren[r-1]) * (a[i].x - a[mid].x)) * 2 <= T) return true;
//    }
    return false;
}
int main() {
    scanf("%d %lld", &n, &T);
    for (int i = 1; i <= n; i++) scanf("%d", &a[i].x);
    for (int i = 1; i <= n; i++) scanf("%d", &a[i].a);
    sort(a+1, a+1+n);
    a[0].x = 0;
    for (int i = 1; i <= n; i++) {
        pren[i] = pren[i-1] + a[i].a;
        pres[i] = pres[i-1] + (a[i].x - a[i-1].x) * pren[i-1];
    }
    a[n+1].x = 1000000000;
    for (int i = n; i >= 1; i--) {
        sufn[i] = sufn[i+1] + a[i].a;
        sufs[i] = sufs[i+1] + (a[i+1].x - a[i].x) * sufn[i+1];
    }
    LL l = 0, r = 1e10, m = (l + r + 1) >> 1;
    while(l < r) {
        if(check(m)) l = m;
        else r = m-1;
        m = (l + r + 1) >> 1;
//        cout << l << " " << r << endl;
    }
    printf("%lld\n", m);
    return 0;
}
View Code

travel

思路:树形dp

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head
 
const int N = 4e5 + 5, M = 5;
int a[N];
vector<int>g[N];
LL F[N][5], G[N][5];
void dfs(int o, int u) {
    LL sum[2][M][M] = {0}, tmp[M][M] = {0};
    int now = 0;
    for (int v : g[u]) {
        if(v != o) {
            dfs(u, v);
            for (int i = 0; i <= 2; i++) {
                for (int j = 0; j <= 3; j++) {
                    tmp[i][j] = 0;
                    sum[now][i][j] = 0;
                }
            }
            for (int i = 0; i <= 3; i++) {
                tmp[0][i] = F[v][i];
                tmp[1][i] = G[v][i];
            }
            for (int i = 0; i <= 2; i++) {
                for (int j = 0; i+j <= 2; j++) {
                    for (int k = 0; k <= 3; k++){
                        for (int l = 0; l+k <= 3; l++) {
                            sum[now][i+j][l+k] = max(sum[now][i+j][l+k], sum[now^1][i][k] + tmp[j][l]);
                            //sum[now][i+j][l+k] = max(sum[now][i+j][l+k], sum[now^1][j][l] + tmp[i][k]);
                        }
                    }
                }
            }
            now ^= 1;
        }
    }
    for (int i = 0; i <= 1; i++) {
        for (int j = 0; j <= 3; j++) {
            G[u][j] = max(G[u][j], sum[now^1][i][j] + a[u]);
        }
    }
    for (int i = 0; i <= 2; i++) {
        for (int j = 1; j <= 3; j++) {
            F[u][j] = max(F[u][j], sum[now^1][i][j-1] + a[u]);
        }
    }
    for (int i = 0; i <= 3; i ++) F[u][i] = max(F[u][i], sum[now^1][0][i]);
}
int main() {
    int n, u, v;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
    for (int i = 1; i < n; i++) {
        scanf("%d %d", &u, &v);
        g[v].pb(u);
        g[u].pb(v);
    }
    dfs(0, 1);
    printf("%lld\n", F[1][3]);
    return 0;
}
View Code

car

思路:风车状

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head
 
const int N = 1e5 + 5;
bool r[N], c[N];
int main() {
    int n, m, x, y;
    scanf("%d %d", &n, &m);
    for (int i = 0; i < m; i++) {
        scanf("%d %d", &x, &y);
        r[x] = true;
        c[y] = true;
    }
    int ans = 0;
    if(n % 2) {
        for (int i = 1; i <= n; i++) {
            if(i == n/2 + 1) continue;
            if(!r[i]) ans++;
        }
        for (int i = 1; i <= n; i++) {
            if(i == n/2 + 1) continue;
            if(!c[i]) ans++;
        }
        if(!r[n/2 + 1] || !c[n/2 + 1]) ans++;
    }
    else {
        for (int i = 1; i <= n; i++) if(!r[i]) ans++;
        for (int i = 1; i <= n; i++) if(!c[i]) ans++;
    }
    printf("%d\n", ans);
    return 0;
}
View Code

farm

思路:随机或者树状数组

随机

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head
 
const int N = 1e6 + 5;
const int MOD = 1e9 + 5;
vector<int>a[N];
vector<LL> s1[N], s2[N];
int b1[N], b2[N];
void add(int x, int y, int k) {
    s1[x][y] += b1[k];
    s2[x][y] += b2[k];
}
void del(int x, int y, int k) {
    s1[x][y] -= b1[k];
    s2[x][y] -= b2[k];
}
void cal(int x, int y) {
    s1[x][y] += s1[x-1][y] + s1[x][y-1] - s1[x-1][y-1];
    s2[x][y] += s2[x-1][y] + s2[x][y-1] - s2[x-1][y-1];
}
int main() {
    srand(time(NULL));
    int n, m, T, x1, y1, x2, y2, k;
    scanf("%d %d %d", &n, &m, &T);
    for (int i = 0; i <= n+2; i++) a[i].resize(m+3), s1[i].resize(m+3), s2[i].resize(m+3);
    for (int i = 1; i < N; i++) {
        b1[i] = (random() % MOD) + N;
        b2[i] = (random() % MOD) + N/2;
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++)
            scanf("%d", &a[i][j]);
    }
    while(T--) {
        scanf("%d %d %d %d %d", &x1, &y1, &x2, &y2, &k);
        add(x1, y1, k);
        del(x1, y2+1, k);
        del(x2+1, y1, k);
        add(x2+1, y2+1, k);
    }
    int ans = 0;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            cal(i, j);
            if(s1[i][j] % b1[a[i][j]] == 0 && s2[i][j] % b2[a[i][j]] == 0) ans++;
        }
    }
    printf("%d\n", n*m - ans);
    return 0;
}
View Code

树状数组

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head
 
const int N = 1e6 + 5;
const int MOD = 1e9 + 5;
vector<int> bit[N], id[N], t[N];
vector<bool>vis[N];
vector<pii>pos[N];
int n, m;
struct query {
    int x1, x2, y1, y2;
}Q[N];
void add(int x, int y, int t) {
    for (int i = x; i <= n; i += i&-i) {
        for (int j = y; j <= m; j += j&-j) {
            bit[i][j] += t;
        }
    }
}
int sum(int x, int y) {
    int ans = 0;
    for (int i = x; i; i -= i&-i) {
        for (int j = y; j; j -= j&-j) {
            ans += bit[i][j];
        }
    }
    return ans;
}
int main() {
    int T, k, mx = 0, a;
    scanf("%d %d %d", &n, &m, &T);
    for (int i = 0; i <= n+2; i++) bit[i].resize(m+3), vis[i].resize(m+3), t[i].resize(m+3);
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            scanf("%d", &a);
            pos[a].push_back({i, j});
            mx = max(mx, a);
        }
    }
    for (int i = 0; i < T; i++) {
        scanf("%d %d %d %d %d", &Q[i].x1, &Q[i].y1, &Q[i].x2, &Q[i].y2, &k);
        id[k].push_back(i);
        mx = max(mx, k);
    }
    for (int i = 1; i <= mx; i++) {
        for (int j = 0; j < pos[i].size(); j++) {
            if(sum(pos[i][j].fi, pos[i][j].se) != 0) vis[pos[i][j].fi][pos[i][j].se] = true;
        }
        for (int j = 0; j < id[i].size(); j++) {
            add(Q[id[i][j]].x1, Q[id[i][j]].y1, 1);
            add(Q[id[i][j]].x1, Q[id[i][j]].y2 + 1, -1);
            add(Q[id[i][j]].x2 + 1, Q[id[i][j]].y1, -1);
            add(Q[id[i][j]].x2 + 1, Q[id[i][j]].y2 + 1, 1);
        }
        for (int j = 0; j < pos[i].size(); j++) {
            if(!vis[pos[i][j].fi][pos[i][j].se]) {
                t[pos[i][j].fi][pos[i][j].se] = sum(pos[i][j].fi, pos[i][j].se);
            }
        }
    }
    int ans = 0;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            if(!vis[i][j]) {
                if(t[i][j] != sum(i, j)) ans++;
            }
            else ans++;
        }
    }
    printf("%d\n", ans);
    return 0;
}
View Code

carpet

思路:hash+KMP找最小循环节,然后用二维单调队列求区间最小

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head
 
const int N = 1e6 + 5;
const int MOD = 1e9 + 7;
const int INF = 0x7f7f7f7f;
string s[N];
vector<int>cost[N], mx[N];
int row[N], col[N], nxt[N];
int get_loop(int a[], int n) {
    nxt[0] = -1;
    for (int i = 1; i < n; i++) {
        int j = nxt[i-1];
        while(a[j+1] != a[i] && j >= 0) j = nxt[j];
        if(a[j+1] == a[i]) nxt[i] = j+1;
        else nxt[i] = -1;
    }
    return n - (nxt[n-1]+1);
}
int main() {
    fio;
    int n, m;
    cin >> n >> m;
    for (int i = 0; i < n; i++) cin >> s[i];
    for (int i = 0; i < n; i++) cost[i].resize(m+2), mx[i].resize(m+2);
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++)
            cin >> cost[i][j];
    }
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            row[i] = (233LL * row[i] + s[i][j]) % MOD;
            col[j] = (233LL * col[j] + s[i][j]) % MOD;
        }
    }
    int a = get_loop(col, m), b = get_loop(row, n);
    deque<int>q;
    for (int i = 0; i < n; i++) {
        q.clear();
        for (int j = 0; j < m; j++) {
            while(!q.empty() && cost[i][q.back()] <= cost[i][j]) q.pop_back();
            q.push_back(j);
            while(!q.empty() && q.front() < j - a + 1) q.pop_front();
            mx[i][j] = cost[i][q.front()];
        }
    }
    int ans = INF;
    for (int j = a-1; j < m; j++) {
        q.clear();
        for (int i = 0; i < n; i++) {
            while(!q.empty() && mx[q.back()][j] <= mx[i][j]) q.pop_back();
            q.push_back(i);
            while(!q.empty() && q.front() < i - b + 1) q.pop_front();
            if(i >= b-1) {
                ans = min(ans, mx[q.front()][j]);
            }
        }
    }
    cout << 1LL * ans * (a+1) * (b+1) << endl;
    return 0;
}
View Code

牛客网暑期ACM多校训练营(第三场)

PACM Team

思路:背包,用short类型开数组

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define fi first.first.first
#define se first.first.second
#define th first.second
#define fo second
using namespace std;
const int maxn=40;
int p[maxn],a[maxn],c[maxn],m[maxn],g[maxn];
short dp[38][38][38][38][38];
bool cat[38][38][38][38][38];
vector<int> ans;
int main(){
    int n;
    int P,A,C,M;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d%d%d%d%d",p+i,a+i,c+i,m+i,g+i);
    scanf("%d%d%d%d",&P,&A,&C,&M);
    int i,j,k,l,q;
    for(i=1;i<=n;i++)
        for(j=0;j<=P;j++)
            for(k=0;k<=A;k++)  
                for(l=0;l<=C;l++)
                    for(q=0;q<=M;q++){
                        if(j>=p[i]&&k>=a[i]&&l>=c[i]&&q>=m[i]){
                            cat[i][j][k][l][q]=1;
                            dp[i][j][k][l][q]=dp[i-1][j-p[i]][k-a[i]][l-c[i]][q-m[i]]+g[i];
                              
                        }
                        if(dp[i-1][j][k][l][q]>=dp[i][j][k][l][q])dp[i][j][k][l][q]=dp[i-1][j][k][l][q],cat[i][j][k][l][q]=0;
                    }
    short ansp,ansa,ansc,ansm;
    int maxans=0;
    for(int j=0;j<=P;j++)
        for(int k=0;k<=A;k++)  
            for(int l=0;l<=C;l++)
                for(int q=0;q<=M;q++)
                    if(dp[n][j][k][l][q]>maxans)ansp=j,ansa=k,ansc=l,ansm=q,maxans=dp[n][j][k][l][q];
    if(maxans==0)return cout<<0,0;
    for(int i=n;i>=1;i--){
        if(cat[i][ansp][ansa][ansc][ansm]){
            ans.push_back(i);
            ansp-=p[i],ansa-=a[i],ansc-=c[i],ansm-=m[i];
        }
    }
    cout<<ans.size()<<endl;
    for(int i=0;i<ans.size();i++)cout<<ans[i]-1<<' ';
    return 0;
}
View Code

Expected Number of Nodes

Shuffle Cards

思路:splay实现区间反转

#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;
int read(){
    char c;int x;while(c=getchar(),c<'0'||c>'9');x=c-'0';
    while(c=getchar(),c>='0'&&c<='9') x=x*10+c-'0';return x;
}
int n,m,root;
struct Splay{
    int fa[MAXN],son[MAXN][2],siz[MAXN],add[MAXN];
    void up(int k){
        siz[k]=siz[son[k][0]]+siz[son[k][1]]+1;
    }
    void down(int k){
        if(add[k]){
            swap(son[k][0],son[k][1]);
            add[son[k][0]]^=1;add[son[k][1]]^=1;
            add[k]=0;
        }
    }
    void rotate(int x,int &k){
        int f=fa[x],gran=fa[f],opt;
        opt=(son[f][1]==x);
        if(f==k) k=x;else son[gran][son[gran][1]==f]=x;
        son[f][opt]=son[x][opt^1];fa[son[f][opt]]=f;
        son[x][opt^1]=f;fa[f]=x;fa[x]=gran;
        siz[x]=siz[f];up(f);
    }
    void splay(int x,int &k){
        while(x!=k){
            int f=fa[x],gran=fa[f];
            if(f!=k) rotate((son[f][0]==x)^(son[gran][0]==f)?x:f,k);
            rotate(x,k);
        }
    }
    void build(int l,int r,int f){
        if(l>r) return;
        int mid=(l+r)>>1;if(mid<f) son[f][0]=mid;else son[f][1]=mid;
        fa[mid]=f;siz[mid]=1;
        if(l==r) return;
        build(l,mid-1,mid);build(mid+1,r,mid);
        up(mid);
    }
    int find(int x,int k){
        down(x);int s=siz[son[x][0]];
        if(s+1==k) return x;
        if(k<=s) return find(son[x][0],k);
        else return find(son[x][1],k-s-1);
    }
    void revers(int l,int r){
        int x=find(root,l),y=find(root,r+2);
        splay(x,root);splay(y,son[root][1]);
        int pl=son[y][0];add[pl]^=1;
    }
}T;
int main()
{
    n=read();m=read();
    root=(n+3)>>1;T.build(1,n+2,root);
    for(int i=1;i<=m;i++){
        int l=read(),r=read();
        r=l+r-1;
        T.revers(1,l-1);
        T.revers(l,r);
        T.revers(1,r);
    }
    for(int i=2;i<=n+1;i++) printf("%d ",T.find(root,i)-1);
    return 0;
}
View Code

Encrypted String Matching

Sort String

思路:字符串hash+排序

代码:

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ULL;
typedef pair<ULL,ULL> pll;
typedef pair<int,int> pii;
const int maxn=1000010;
const int base=233;
char s[maxn];
ULL POW[maxn];
pll Hash[maxn];
pii p[maxn];
vector<int> vec[maxn];
int main(){
    scanf("%s",s);
    int n=strlen(s);
    ULL now=0;
    POW[0]=1;
    for(int i=1;i<=n;++i)POW[i]=POW[i-1]*base;
    for(int i=0;i<n;++i)now=now*base+(s[i]-'a'+1);
    for(int i=0;i<n;i++){
        Hash[i]={now,(ULL)i};
        now=now-(s[i]-'a'+1)*POW[n-1];
        now=now*base+(s[i]-'a'+1);
    }
    sort(Hash,Hash+n);
    int anscnt=0;
    for(int i=0;i<n;i++){
        if(!i||Hash[i-1].first!=Hash[i].first)++anscnt,p[anscnt]={Hash[i].second,anscnt};
        vec[anscnt].emplace_back(Hash[i].second);
    }
    sort(p+1,p+1+anscnt);
    printf("%d\n",anscnt);
    for(int i=1;i<=anscnt;i++){
        printf("%d ",vec[p[i].second].size());
        for(auto w:vec[p[i].second]){
            printf("%d ",w);
        }
        puts("");
    }
    return 0;
}
View Code

Sum Of Digit

Coloring Tree

Diff-prime Pairs

思路:枚举小于n的素数,每个素数和比它小的素数匹配,最后答案乘2

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head

const int N = 1e7 + 5;
bool vis[N];
vector<int>p;
void seive() {
    for (int i = 2; i < N; i++) {
        if(!vis[i]) {
            p.push_back(i);
            for (int j = i+i; j < N; j += i) vis[j] = true;
        }
    }
}
int main() {
    seive();
    int n;
    scanf("%d", &n);
    LL ans = 0;
    for (int i = 0; i < p.size(); i++) {
        if(p[i] > n) break;
        ans += n/p[i] * 1LL * i;
    }
    ans *= 2; 
    printf("%lld\n", ans);
    return 0;
}
View Code

Expected Size of Random Convex Hull

Distance to Work

牛客网暑期ACM多校训练营(第四场)

Ternary String

Interval Revisited

Chiaki Sequence Reloaded

Another Distinct Values

思路:构造,花了几个小时想了一个超复杂的构造TAT,看看别人的构造,感觉自己蠢哭了

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head
 
const int N = 555;
int a[N][N];
map<int, int>mp;
bool check(int n) {
    mp.clear();
 
    for (int i = 1; i <= n; i++) {
        int s = 0;
        for (int j = 1; j <= n; j++) {
            s += a[i][j];
        }
        mp[s]++;
    }
 
    for (int i = 1; i <= n; i++) {
        int s = 0;
        for (int j = 1; j <= n; j++) {
            s += a[j][i];
        }
        mp[s]++;
    }
    if(mp.size() == n*2) return true;
    else return false;
}
int main() {
    fio;
    int T, n;
    cin >> T;
    while(T--) {
        cin >> n;
        if(n&1) {
            cout << "impossible" << endl;
            continue;
        }
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++)
                a[i][j] = -1;
        }
        for (int i = 1; i <= n/2; i++) {
            for (int j = 1; j <= n/2; j++) {
                a[i][j] = 1;
                a[i+n/2][j+n/2] = -1;
                if(i + j > n/2 + 1) a[i][j+n/2] = 0;
                else a[i][j+n/2] = 1;
            }
        }
        int tot = n/2, cnt, res;
        if(tot&1) cnt = tot/2+1;
        else cnt = tot/2;
        res = tot - cnt;
        for (int i = 1; i <= cnt; i++) {
            for (int j = 1; j <= cnt; j++) {
                if(i + j > cnt + ((tot+1)%2)) a[i+tot][j] = 0;
                else a[i+tot][j] = 1;
            }
        }
        for (int i = 1; i <= res; i++) {
            for (int j = 1; j <= res; j++) {
                if(i + j > res) a[i+tot+cnt][j+cnt] = 0;
                else  a[i+tot+cnt][j+cnt] = -1;
            }
        }
        cout << "possible" << endl;
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++)
                cout << a[i][j] << " ";
            cout << endl;
        }
 
    }
    return 0;
}
View Code

Skyline

Beautiful Garden

思路:模拟

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long long LL;
 
char s[2005][2005];
 
bool check(char a,char b, char c,char d)
{
    if(a==b&&a==c&&a==d) return true;
    return false;
}
 
int main()
{
    int t;
    while(scanf("%d",&t)!=EOF)
    {
        while(t--)
        {
            int n,m;
            scanf("%d%d",&n,&m);
            for(int i=0;i<n;i++) scanf("%s",s[i]);
            int Maxc=INT_MAX;
            int Maxr=INT_MAX;
            for(int i=0;i<n;i++)
            {
                int cnt=0;
                for(int j=0;j<m/2;j++)
                {
                    if(s[i][j]==s[i][m-j-1]) cnt++;
                    else {
                        cnt++;
                        break;
                    }
                }
                Maxr=min(Maxr,cnt);
            }
            for(int i=0;i<m;i++)
            {
                int cnt=0;
                for(int j=0;j<n/2;j++)
                {
                    if(s[j][i]==s[n-j-1][i]) cnt++;
                    else {
                        cnt++;
                        break;
                    }
                }
                Maxc=min(Maxc,cnt);
            }
            Maxc--;
            Maxr--;
            printf("%d\n",Maxc*Maxr);
        }
    }
}
View Code

Maximum Mode

思路:统计一下出现次数为i的数的个数,然后从小到大枚举数a[i],检查一下将所有出现次数大于等于a[i]出现次数的数删掉成都小于a[i]的个数,可行就更新答案。

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head
 
const int N = 1e5 + 5 ;
int a[N];
int t[N];
LL sum[N];
int main() {
    int T, n, m;
    scanf("%d", &T);
    while(T--) {
        scanf("%d%d", &n, &m);
        for (int i = 0; i < n; i++) scanf("%d", &a[i]);
        for (int i = 0; i <= n; i++) t[i] = 0;
        sort(a, a+n);
        int now = 1;
        for (int i = 1; i < n; i++) {
            if(a[i] != a[i-1]) {
                t[1]++;
                t[now+1]--;
                now = 1;
            }
            else now++;
        }
        t[1]++;
        t[now+1]--;
        now = 1;
        for (int i = 1; i <= n; i++) t[i] += t[i-1];
        for (int i = 1; i <= n; i++) sum[i] = sum[i-1] + t[i];
        int ans = -1;
        for (int i = 1; i < n;i++) {
            if(a[i] != a[i-1]) {
                if(t[now] - 1 + sum[n] - sum[now] <= m) ans = a[i-1];
                now = 1;
            }
            else now++;
        }
        if(t[now] - 1 + sum[n] - sum[now] <= m) ans = a[n-1];
        printf("%d\n", ans);
    }
    return 0;
}
View Code

Double Palindrome

Permutation

Hash Function

牛客网暑期ACM多校训练营(第五场) 

gpa

思路:01分数规划

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head
 
const int N = 1e5 + 5;
const double eps = 1e-7;
int n, k;
pii a[N];
double t[N];
bool check(double m) {
    for (int i = 0; i < n; i++) t[i] = (double)a[i].fi*a[i].se - m*a[i].fi;
    sort(t, t+n);
    double tt = 0;
    for (int i = k; i < n; i++) tt += t[i];
    //cout<< fixed << setprecision(6)<< tt << endl;
    return tt >= 0;
}
int main() {
    scanf("%d %d", &n, &k);
    for (int i = 0; i < n; i++) scanf("%d", &a[i].fi);
    for (int i = 0; i < n; i++) scanf("%d", &a[i].se);
    double l = 0, r = 1e4 + 5, m = (l+r)/2;
    while(l + eps< r) {
        if(check(m)) l = m;
        else r = m;
        m = (l+r) / 2;
    }
    printf("%.10f\n", m);
    return 0;
}
View Code

div

grf

inv

room

take

思路:考虑每个位置对答案的贡献,但前位置被替换当且仅当前面所有比当前小的都没有被替换(即之前比当前小的盒子的钻石都没有钻石,有1-pj的概率),这个用树状数组维护个前缀积就可以了

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head

const int N = 1e5 + 5;
const int MOD = 998244353;
pii a[N];
LL bit[N];
int n;
vector<int>vc;
LL q_pow(LL n, LL k) {
    LL ans = 1;
    while(k) {
        if(k&1) ans = (ans * n) % MOD;
        n = (n * n) % MOD;
        k >>= 1;
    }
    return ans;
}
void add(int x, LL y) {
    while(x <= n) bit[x] *= y, bit[x] %= MOD, x += x&-x;
}
LL sum(int x) {
    LL ans = 1;
    while(x)  ans *= bit[x], ans %= MOD, x -= x&-x;
    return ans;
}
int main() {
    scanf("%d", &n);
    for (int i = 0; i < n; i++) scanf("%d %d", &a[i].fi, &a[i].se), vc.pb(a[i].se);
    sort(vc.begin(), vc.end());
    vc.erase(unique(vc.begin(), vc.end()), vc.end());
    for (int i = 0; i < n; i++) a[i].fi = (1LL * a[i].fi * q_pow(100, MOD-2)) % MOD, a[i].se = lower_bound(vc.begin(), vc.end(), a[i].se) - vc.begin(), a[i].se = n - a[i].se;
    for (int i = 0; i <= n; i++) bit[i] = 1;
    LL ans = 0;
    for (int i = 0; i < n; i++) {
        ans = (ans + a[i].fi * sum(a[i].se - 1)) % MOD;
        add(a[i].se, (1 - a[i].fi) % MOD);
    }
    ans = (ans + MOD) % MOD;
    printf("%lld\n", ans);
    return 0;
}
View Code

max

思路:找第一个i和n互质,质数之间距离很短

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head

int main() {
    fio;
    int c, n;
    cin >> c >> n;
    n /= c;
    for (int i = n; i >= 1; i--) {
        if(__gcd(i, n) == 1) {
            cout << 1LL * n * i * c * c << endl;
            return 0;
        }
    }
    cout << -1 << endl;
    return 0;
}
View Code

subseq

vcd

思路:首先,一个点的集合肯定可以,其次,二个点如果想满足题意,那么y要求不同,三点的集合如果想满足题意,那么要三个点构成“<”形状,最后,超过三个点的集合都不可以。

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head

const int N = 1e5 + 5;
const int MOD = 998244353;
pii a[N];
vector<int>vc;
int n, t[N], bit[N];
void add(int x) {
    while(x <= n) bit[x]++, x += x&-x;
}
int sum(int x) {
    int ans = 0;
    while(x) ans += bit[x], x -= x&-x;
    return ans;
}
bool cmp(pii a, pii b) {
    return a.fi > b.fi;
}
LL q_pow(LL n, LL k) {
    LL ans = 1;
    while(k) {
        if(k&1) ans = (ans * n) % MOD;
         n = (n * n) % MOD;
         k >>= 1;
    }
    return ans;
}
int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) scanf("%d %d", &a[i].fi, &a[i].se), vc.pb(a[i].se);
    sort(vc.begin(), vc.end());
    vc.erase(unique(vc.begin(), vc.end()), vc.end());
    for (int i = 1; i <= n; i++) a[i].se = lower_bound(vc.begin(), vc.end(), a[i].se) - vc.begin() + 1, t[a[i].se]++;
    sort(a+1, a+1+n, cmp);
    LL ans = 0;
    for (int i = 1; i <= n; i++) ans += 1LL*t[i]*(n-t[i]), ans %= MOD;
    ans = (ans * q_pow(2, MOD-2)) % MOD;
    ans = (ans + n) % MOD;
    int pos = 1;
    for (int i = 1; i <= n; i++) {
        if(a[i].fi != a[i-1].fi) {
            while(pos < i) {
                add(a[pos++].se);
            }
        }
        int up = sum(n) - sum(a[i].se);
        int down = sum(a[i].se - 1);
        ans += 1LL * up * down;
        ans %= MOD;
    }
    printf("%lld\n", ans);
    return 0;
}
View Code

plan

思路:答案肯定是某一种房间选了很多,我们暴力房间少的那一个,3个就够了

View Code

牛客网暑期ACM多校训练营(第六场) 

Singing Contest

思路:模拟+贪心,每次歌手都唱大于对方最大值的歌

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head
 
const int N = 2e4 + 5;
set<int>s[N];
int mx[N];
bool vis[N];
int main() {
    int T, n, t;
    scanf("%d", &T);
    for (int cs = 1; cs <= T; cs++) {
        scanf("%d", &n);
        mem(mx, 0);
        for (int i = 1; i <= (1<<n); i++) {
            s[i].clear();
            for (int j = 1; j <= n; j++) {
                scanf("%d", &t);
                s[i].insert(t);
                mx[i] = max(mx[i], t);
            }
        }
        mem(vis, false);
        for (int i = 1; i <= n; i++) {
            int last = -1;
            for (int j = 1; j <= (1<<n); j++) {
                if(!vis[j]) {
                    if(last == -1) last = j;
                    else {
                        int mm = mx[last], mmm = mx[j];
                        if(mm > mmm) {
                            vis[j] = true;
                            auto it = s[last].lower_bound(mmm);
                            s[last].erase(it);
                            mx[last] = 0;
                            for (auto t : s[last]) mx[last] = max(mx[last], t);
                        }
                        else {
                            vis[last] = true;
                            auto it = s[j].lower_bound(mm);
                            s[j].erase(it);
                            mx[j] = 0;
                            for (auto t : s[j]) mx[j] = max(mx[j], t);
                        }
                        last = -1;
                    }
                }
            }
        }
        for (int i = 1; i <= (1<<n); i++)
        if(!vis[i]) {
            printf("Case #%d: %d\n", cs, i);
            break;
        }
    }
    return 0;
}
View Code

Endless Pallet

Generation I

思路:考虑第i次操作i ~ n的所有集合都加相同的数,所以我们只考虑每个数第一次出现在哪里,因为如果这个数在后面有没有出现过是没有关系的,后面的所有集合都有这个数

考虑总共出现了k个数,第一个位置肯定出现了一个数,所以从n-1个位置中选k-1个位置,再加上第一个位置构成k个位置,作为这k个数第一次出现的位置,总共有C(n-1, k-1)中

然后考虑这k个数有多少种可能,有A(m, k)可能,所以对于出现k个数,有C(n-1, k-1) * A(m, k)中可能,然后将k从1枚举min(n, m)求个和就可以了

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head

const int N = 1e6 + 5;
const int MOD = 998244353;
int inv[N];
void init() {
    inv[1] = 1;
    for (int i = 2; i < N; i++) inv[i] = (MOD - MOD/i) * 1LL * inv[MOD%i] % MOD;
}
int main() {
    init();
    int T;
    LL n, m;
    scanf("%d", &T);
    for (int cs = 1; cs <= T; cs++) {
        scanf("%lld %lld", &n, &m);
        int up = min(n, m);
        LL ans = 0, C = 1, A = m%MOD;
        for (int i = 1; i <= up; i++) {
            ans = (ans + C * A) % MOD;
            n--;
            m--;
            C = ((C * n) % MOD * inv[i]) % MOD;
            A = (A * m) % MOD;
        }
        printf("Case #%d: %lld\n", cs, ans);
    }
    return 0;
}
View Code

Bulbasaur

思路:发现每个身体只能连一个头,所以对于每个身体选一个最大的权值,它连哪个头都无所谓,这样是最优的

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head

const int N = 1e5 + 5;
int mx[N];
int main() {
    int T, a, b, c, n, m, k;
    scanf("%d", &T);
    for (int cs = 1; cs <= T; cs++) {
        scanf("%d %d %d", &n, &m, &k);
        for (int i = 1; i <= n; i++) mx[i] = 0;
        for (int i = 0; i < k; i++) {
            scanf("%d %d %d", &a, &b, &c);
            mx[b] = max(c, mx[b]);
        }
        LL ans = 0;
        for (int i = 1; i <= m; i++) ans += mx[i];
        printf("Case #%d: %lld\n", cs, ans);
    }
    return 0;
}
View Code

Charmander

Squirtle

Pikachu

Eevee

Team Rocket

Heritage of skywalkert

思路:由于数据随机,所以最大的几个数有很大可能互质,所以挑出最大的几个数两两求lcm取最大,可以用stl里面的nth_element(),很强大

如果用set的话,注意保存一下当前set的最小值,与最小值判断一下需不需要加进set,否则的化常数太大会超时

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
unsigned int  A,B,C;
unsigned int  x=A,y=B,z=C;
inline unsigned int  tang()
{
    unsigned int  t;
    x^=x<<16;
    x^=x>>5;
    x^=x<<1;
    t=x;
    x=y;
    y=z;
    z=t^x^y;
    return z;
}
unsigned int  num[10000005];
set<unsigned int>mx;
inline unsigned long long gcd(unsigned long long a, unsigned long long b) {
    return b ? gcd(b, a%b): a;
}
inline unsigned long long lcm(unsigned long long x,unsigned long long y)
{
    return x/__gcd(x,y)*y;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin>>t;
    for(int tt=1;tt<=t;tt++)
    {
        int n;
        cin>>n>>A>>B>>C;
        x=A,y=B,z=C;
        mx.clear();
        unsigned int mn;
        for(int i=1;i<=n;i++)
        {
            num[i]=tang();
            if(mx.size() < 20) mx.insert(num[i]), mn = *mx.begin();
            else {
                if(num[i] > mn) {
                    mx.insert(num[i]);
                    mx.erase(mx.begin());
                    mn = *mx.begin();
                }
            }
        }
        unsigned long long Max=0;
        vector<unsigned int>vc;
        for (auto x:mx) vc.push_back(x);
        for (int i = 0; i < vc.size(); i++) {
            for (int j = i+1; j < vc.size(); j++) {
                Max = max(Max, lcm(vc[i], vc[j]));
            }
        }
        cout<<"Case #"<<tt<<": "<<Max<<endl;
    }
    return 0;
}
View Code

牛客网暑期ACM多校训练营(第七场)

Minimum Cost Perfect Matching

思路:对于每个i找比i小的~i,将两个连接起来,这样最小花费是0

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head
 
const int N = 5e5 + 5;
bool vis[N];
int a[N];
int main() {
    int n;
    scanf("%d", &n);
    for (int i = n - 1; i >= 0; i--) {
        int t = 0;
        bool f = false;
        for (int j = 29; j >= 0; j--) {
            if((i & (1 << j)) == 0) {
                if(f) t = t*2 + 1;
            }
            else {
                f = true;
                t = t*2;
            }
        }
        if(!vis[i] && !vis[t]) {
            a[i] = t;
            a[t] = i;
            vis[t] = true;
            vis[i] = true;
        }
    }
    for (int i = 0; i < n; i++) printf("%d%c", a[i], " \n"[i==n]);
    return 0;
}
View Code

Birthday Problem

Bit Compression

思路:搜索优化,预处理出最后三步的结果

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define pf emplace_front
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stdout);
//head

const int N = (1<<16) + 10, M = (1<<20) + 10;
bool t[20][M];
char s[M];
int dp[5][N], ans = 0;
void init(int n) {
    int up = 1;
    for (int i = 0; i < n; i++) up = up * 3;
    for (int i = 0; i < (1<<(1<<n)); i++) {
        for (int j = 0; j < (1<<n); j++) {
            if(i & (1<<j)) t[n][j] = 1;
            else t[n][j] = 0;
        }
        for (int j = 0; j < up; j++) {
            int tmp = j;
            for (int k = n-1; k >= 0; k--) {
                for (int l = 0; l < (1<<k); l++) {
                    if(tmp%3 == 0) t[k][l] = t[k+1][l*2]^t[k+1][l*2+1];
                    else if(tmp%3 == 1) t[k][l] = t[k+1][l*2]&t[k+1][l*2+1];
                    else t[k][l] = t[k+1][l*2]|t[k+1][l*2+1];
                }
                tmp /= 3;
            }
            dp[n][i] += t[0][0];
        }
    }
}
void dfs(int n) {
    for (int i = 0; i < (1<<n); i++) t[n][i] = t[n+1][i*2]^t[n+1][i*2+1];
    if(n == 3) {
        int st = 0;
        for (int i = 0; i < (1<<n); i++) st = st*2 + t[n][i];
        ans += dp[n][st];
    }
    else dfs(n-1);
    for (int i = 0; i < (1<<n); i++) t[n][i] = t[n+1][i*2]&t[n+1][i*2+1];
    if(n == 3) {
        int st = 0;
        for (int i = 0; i < (1<<n); i++) st = st*2 + t[n][i];
        ans += dp[n][st];
    }
    else dfs(n-1);
    for (int i = 0; i < (1<<n); i++) t[n][i] = t[n+1][i*2]|t[n+1][i*2+1];
    if(n == 3) {
        int st = 0;
        for (int i = 0; i < (1<<n); i++) st = st*2 + t[n][i];
        ans += dp[n][st];
        return ;
    }
    else dfs(n-1);
}
int main() {
    int n;
    scanf("%d", &n);
    scanf("%s", s);
    init(min(n, 3));
    if(n <= 3) {
        int st = 0;
        for (int i = 0; i < (1<<n); i++) st = st*2 + (s[i] == '1');
        printf("%d\n", dp[n][st]);
    }
    else {
        for (int i = 0; i < (1<<n); i++) t[n][i] = s[i] == '1';
        dfs(n-1);
        printf("%d\n", ans);
    }
    return 0;
}
View Code

Inverse Inverse Problem

Counting 4-Cliques

思路:打表可以发现当k很大时可以由t个点的完全图加上另外5个点与t个点中的部分点相连构成k个4元组,即存在t, a, b, c, d, e,

使得C(t, 4) + C(a, 3) + C(b, 3) + C(c, 3) + C(d, 3)+ C(e, 3) == k

预处理C(e, 3), 暴力枚举a,b, c, d

或者预处理C(d, 3) + C(e, 3) , 暴力枚举a,b, c 

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head

int C4[100], C3[100], t;
int C(int n, int m) {
    int ans = 1;
    if(n < m) return 0;
    for (int i = n; i >= n-m+1; i--) ans *= i;
    for (int i = 1; i <= m; i++) ans /= i;
    return ans;
}
void solve(int a, int b, int c, int d, int e) {
    printf("%d %d\n", t+5, C(t, 2) + a + b + c + d + e);
    for (int i = 1; i <= t; i++) {
        for (int j = i+1; j <= t; j++)
            printf("%d %d\n", i, j);
    }
    for (int i = 1; i <= a; i++) printf("%d %d\n", i, t+1);
    for (int i = 1; i <= b; i++) printf("%d %d\n", i, t+2);
    for (int i = 1; i <= c; i++) printf("%d %d\n", i, t+3);
    for (int i = 1; i <= d; i++) printf("%d %d\n", i, t+4);
    for (int i = 1; i <= e; i++) printf("%d %d\n", i, t+5);
}
map<int, pii>mp;
int main() {
    int k;
    scanf("%d", &k);
    t = 4;
    for (int i = 3; i <= 80; i++) C4[i] = C(i, 4), C3[i] = C(i, 3);
    while(C4[t+1] <= k) t++;
    t = min(t, 70);
    for (int i = 2; i <= t; i++) {
        for (int j = 2; j <= t; j++) {
            mp[C3[i] + C3[j]] = {i, j};
        }
    }
    for (int i = 2; i <= t; i++) {
        for (int j = i; j <= t; j++) {
            for (int l = j; l <= t; l++) {
                if(mp.find(k - C4[t] - C3[i] - C3[j] - C3[l]) != mp.end()) {
                    solve(i, j, l, mp[k - C4[t] - C3[i] - C3[j] - C3[l]].fi, mp[k - C4[t] - C3[i] - C3[j] - C3[l]].se);
                    return 0;
                }
            }
        }
    }
    return 0;
}
View Code

Mindiff and Maxdiff

Rock-Paper-Scissors Tournament

Class Division

Tree Subset Diameter

Sudoku Subrectangles

思路:O(n*m)处理每个点往右能到哪里,往下能到哪里,然后O(52*n*m)对于每个点往右扫列最小,然后往下求行最小

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stdout);
//head

const int N = 1e3 + 5;
char s[N][N];
int a[N][N], r[N][N], d[N][N], mn[N][N];
int main() {
    int n, m;
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; i++) {
        scanf("%s", s[i]+1);
        for (int j = 1; j <= m; j++)
            if(isupper(s[i][j])) a[i][j] = s[i][j] - 'A' + 26;
            else a[i][j] = s[i][j] - 'a';
    }
    for (int i = 1; i <= n; i++) {
        LL st = 0;
        int pre = 1;
        for (int j = 1; j <= m; j++) {
            if(j > 1) st ^= 1LL << a[i][j-1];
            r[i][j] = m;
            bool f = true;
            for (int k = pre; k <= m; k++) {
                if(st & (1LL << a[i][k])) {
                    f = false;
                    r[i][j] = k-1;
                    pre = k;
                    break;
                }
                st |= 1LL << a[i][k];
            }
            if(f) pre = m+1;
        }
    }
    for (int j = 1; j <= m; j++) {
        LL st = 0;
        int pre = 1;
        for (int i = 1; i <= n; i++) {
            if(i > 1) st ^= 1LL << a[i-1][j];
            d[i][j] = n;
            bool f = true;
            for (int k = pre; k <= n; k++) {
                if(st & (1LL << a[k][j])) {
                    f = false;
                    d[i][j] = k-1;
                    pre = k;
                    break;
                }
                st |= 1LL << a[k][j];
            }
            if(f) pre = n+1;
        }
    }
    LL ans = 0;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            mn[i][j] = d[i][j];
            for (int k = j+1; k <= r[i][j]; k++) {
                mn[i][k] = min(mn[i][k-1], d[i][k]);
            }
            int now = r[i][j];
            for (int k = i; k <= d[i][j]; k++) {
                now = min(now, r[k][j]);
                while(mn[i][now] < k && now >= j) now --;
                if(now < j) break;
                ans += now - j + 1;
            }
        }
    }
    printf("%lld\n", ans);
    return 0;
}
View Code

牛客网暑期ACM多校训练营(第八场)

Connecting segments

Filling pools

oeis公式

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stdout);
//head


const int MOD = 998244353;
const int N = 3e5 + 5;
LL C[N], NN[N], inv[N], p[N], ans = 0;
LL q_pow(LL n, LL k) {
    LL ans = 1;
    while(k) {
        ans = (ans * n) % MOD;
        n = (n * n) % MOD;
        k >>= 1;
    }
    return ans;
}
void init(int n) {
    n--;
    inv[1] = 1;
    for (int i = 2; i <= n; i++) inv[i] = (MOD - MOD/i) * inv[MOD%i] % MOD;
    p[0] = 1;
    for (int i  = 1; i <= n; i++) p[i] = (p[i-1] * 2) % MOD;
    C[0] = 1;
    for (int i = 1; i <= n; i++) C[i] = ((C[i-1] * (n-i+1)) % MOD * inv[i]) % MOD;
    for (int i = 1; i <= n; i++) NN[i] = (C[i] * C[i-1]) % MOD * inv[n] % MOD;
    for (int i = 1; i <= n; i++) ans = (ans + NN[i] * p[n-i+1]) % MOD;
}
int main() {
    int n;
    scanf("%d", &n);
    if(n == 1) return 0*puts("1");
    init(n);
    printf("%lld\n", ans);
    return 0;
}
View Code

Counting paths

Compressing data

Touring cities

Protecting lawn

Counting regions

思路:立体几何欧拉公式:V - E + F = 2 (V:顶点个数, E:边条数, F:面个数,怎么记忆呢,维数为0的点加上维数为2的面减去维数为1的线等于2)

F = E -  V + 2

首先,将平面图看成立体图(以正多边形为底的立体图),那么问题就转换成已知点个数和边条数来求多面体的面有多少个

内部交点个数(从n个点中选4个顶点连起来):C(n, 4)

所以定点个数:C(n, 4) + n

每个内部交点会多产生两条边,所以边个数: C(n, 2) + C(n, 4) * 2

所以F = E - V + 2 = (C(n, 2) + C(n, 4) * 2) - (C(n, 4) + n)  + 2 = C(n, 2) + C(n, 4) - n + 2 

减去底面所以要减一

答案为C(n, 2) + C(n, 4) - n + 1

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stdout);
//head

const int MOD = 1e9 + 7;
LL q_pow(LL n, LL k) {
    LL ans = 1;
    while(k) {
        if(k&1) ans = (ans * n) % MOD;
        n = (n * n) % MOD;
        k >>= 1;
    }
    return ans;
}
LL C(int n, int m) {
    LL ans = 1;
    for (int i = n; i >= n-m+1; i--) ans = (ans * i) % MOD;
    for (int i = 1; i <= m; i++) ans = (ans * q_pow(i, MOD-2)) % MOD;
    return ans;
}
int main() {
    int n;
    cin >> n;
    LL ans = (C(n, 4) + C(n, 2) - n + 1 + MOD) % MOD;
    cout << ans << endl;
    return 0;
}
View Code

Playing games

Permuting cows

Calculating sums

Decoding graphs

牛客网暑期ACM多校训练营(第九场)

Circulant Matrix

思路:FWT

队友代码:

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,a[530000],b[530000],tot,x,ha=1e9+7,inv2;
int qpow(int a,int b)
{
    int ans=1;
    while(b){if(b&1)ans=ans*a%ha;a=a*a%ha,b>>=1;}
    return ans;
}
void fwt(int *a,int n,int t)
{
    for(int i=1;i<n;i<<=1)
    {
        for(int j=0;j<n;j+=(i<<1))
        for(int k=j;k<i+j;k++)
        {
            int x=a[k],y=a[k+i];
               
            a[k]=(x+y)%ha,a[k+i]=(x-y+ha)%ha;
            if(t)a[k]=a[k]*inv2%ha,a[k+i]=a[k+i]*inv2%ha;
        }
    }
       
}
signed main()
{
    scanf("%lld",&n);
    inv2=qpow(2,ha-2);
    for(int i=0;i<n;i++)scanf("%lld",&a[i]);
    for(int i=0;i<n;i++)scanf("%lld",&b[i]);
    fwt(a,n,0);fwt(b,n,0);
    for(int i=0;i<n;i++)b[i]=b[i]*qpow(a[i],ha-2)%ha;
    fwt(b,n,1);
    for(int i=0;i<n;i++)printf("%lld\n",b[i]);
    return 0;
}
View Code

Enumeration not optimization

Gambling

The number of circuits

Music Game

思路:dp

状态定义:dp[i][0]表示到第i位以0结尾的期望分数,dp[i][1]表示到第i位以1结尾的期望分数

状态转移:dp[i][0] = (1 - p[i]) * (dp[i-1][0] + dp[i-1][1])

dp[i][1] = ∑ ( ∏p[k](j < k <= i) * (dp[j][0] + (1 -  p[j]) * (i - j)^m)) (0<= j < i)

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head
 
const int N = 1e3 + 5;
const int MOD = 1e9 + 7;
LL p[N], pp[N], dp[N][2];
LL q_pow(LL n, LL k) {
    LL ans = 1;
    while(k) {
        if(k&1) ans = (ans * n) % MOD;
        n = (n * n) % MOD;
        k >>= 1;
    }
    return ans;
}
int main() {
    int n, m;
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; i++) scanf("%lld", &p[i]);
    for (int i = 0; i <= n; i++) p[i] = (p[i] * q_pow(100, MOD-2)) % MOD, pp[i] = (1 - p[i] + MOD) % MOD;
    dp[0][0] = dp[1][0] = 0;
    for (int i = 1; i <= n; i++) {
        LL t = p[i];
        dp[i][1] = 0;
        for (int j = i-1; j >= 0; j--) {
            dp[i][1] = (dp[i][1] + t * (dp[j][0] + pp[j] * q_pow(i-j, m) % MOD) % MOD) % MOD;
            t = (t * p[j]) % MOD;
        }
        dp[i][0] = (pp[i] * (dp[i-1][0] + dp[i-1][1])) % MOD;
    }
    printf("%lld\n", (dp[n][1] + dp[n][0]) % MOD);
    return 0;
}
View Code

Typing practice

思路:KMP

队友代码:

#include<bits/stdc++.h>
using namespace std;
long long dp[1010][2];
int nnxt[5][100010];
int ans[100010];
void init(int MIN){
    for(int i=0;i<=100010;i++)ans[i]=MIN;
}
void getNext(string ptr, int next[]){
    next[0] = -1;
    int j = 0, k = -1;
    while(j < ptr.size()){
        if (k == -1 || ptr[j] == ptr[k]){
            if (ptr[++j] == ptr[++k])
                next[j] = next[k];
            else next[j] = k;
        } else k = next[k];
    }
}
int I[100010],J[100010];
bool match[100010];
int KMP(string now, string ptr,int next[]){
    string str;
    int cnt = 0;
    int i = 0, j = 0;
    int pos = 0;
    while(pos < now.length()){
        if(now[pos]=='-'){
            if(str.length())str.pop_back();
            i=I[str.length()],j=J[str.length()];
            cnt+=match[str.length()];
            pos++;
            if(match[str.length()])ans[pos]=0;
            else ans[pos]=min(ans[pos],(int)ptr.length()-j);
//          cout<<j<<' ';
            continue;
        }
        else{
            str.push_back(now[pos]);
            match[str.length()]=0;
            while(i < str.size()){
                if (j == -1 || str[i] == ptr[j]){
                    i++, j++;      
                    if (j == ptr.size()){
                        cnt++; j = next[j];
                        match[str.length()]=1;
                        ans[pos+1]=0;
                        //cout<<j<<endl;
                    }
                }
                else j = next[j];
            }
            I[str.length()]=i,J[str.length()]=j;
            pos++;
            ans[pos]=min(ans[pos],(int)ptr.length()-j);
//          cout<<j<<' ';
        }
    }
    return cnt;
}
 
int main(){
    int n;
    string t[5];
    string s;
    int MIN=0x7fffffff;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>t[i];
        getNext(t[i],nnxt[i]);
        MIN=min(MIN,(int)t[i].length());
    }
    init(0x7fffffff);
    cin>>s;
    for(int i=1;i<=n;i++){
//      cout<<"  ";
        KMP(s,t[i],nnxt[i]);
//      cout<<endl;
//
//      cout<<endl;
    }
        cout<<MIN<<endl;
        for(int i=1;i<=s.length();i++)cout<<ans[i]<<endl;   
    return 0;
}
 
View Code

Longest Common Subsequence

Prefix Sum

Juggernaut

Maze

牛客网暑期ACM多校训练营(第十场)

Rikka with Lowbit

思路:每次修改后这个位置的期望值不变,因为加上一个lowbit和减去一个lowbit后取平均值还是原来的值。

队友代码:

#include<bits/stdc++.h>
using namespace std;
const long long mod=998244353;
long long a[100010];
long long pre[100010];
long long POW(long long x,long long n){
    long long re=1,base=x;
    while(n){
        if(n&1)(re*=base)%=mod;
        (base*=base)%=mod;
        n>>=1;
    }
    return re;
}
int main(){
    int T;
    int n,m;
    int u,v,w;
    scanf("%d",&T);
    for(int t=1;t<=T;t++){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%lld",a+i);
        }
        for(int i=1;i<=n;i++){
            pre[i]=(pre[i-1]+a[i])%mod;
        }
        long long pp=POW(2ll,1ll*n*m);
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&u,&v,&w);
            if(u==2){
                printf("%lld\n",((pre[w]-pre[v-1]+mod)%mod)*pp%mod);
            }
        }
    }
    return 0;
}
View Code

Rikka with Burrow-Wheeler Transform

Rikka with Rotate

Rikka with Prefix Sum

思路:推出每个位置i的k阶前缀和的公式∑C(i+k-1, k)*a[j] (1 <= j <= i),然后用差分记录第一种操作的修改(不然保存不下),将差分看成-1阶的前缀和,然后查询的时候将所有出现过的修改都用公式求一下前缀和查询到修改之间有几次第二种操作就是他的阶数,记得要加1,因为我们用差分记录的。

队友代码:

#include<bits/stdc++.h>
using namespace std;
long long fac[200010],inv[200010];
const long long mod=998244353;
int L[200010],R[200010],val[200010],cnt[200010],top,tot;
long long POW(long long x,long long n){
    long long re=1,base=x;
    while(n){
        if(n&1)(re*=base)%=mod;
        (base*=base)%=mod;
        n>>=1;
    }
    return re;
}
long long C(long long n,long long m){
    if(n<0||m<0||n<m)return 0;
    return fac[n]*inv[n-m]%mod*inv[m]%mod;
}
void init(){
    top=0,tot=0;
}
void INIT(){
    fac[0]=1;
    for(int i=1;i<=200001;i++)fac[i]=fac[i-1]*i%mod;
    inv[200001]=POW(fac[200001],mod-2);
    for(int i=200001;i>=1;i--)inv[i-1]=inv[i]*i%mod;
}
int main(){
    INIT();
    int T,n,m,op;
    int l,r,v;
    scanf("%d",&T);
    for(int t=1;t<=T;t++){
        init();
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++){
            scanf("%d",&op);
            if(op==1){
                scanf("%d%d%d",&l,&r,&v);
                L[top]=l,R[top]=r,val[top]=v,cnt[top++]=tot;
            }
            else if(op==2)tot++;
            else{
                long long ans=0;
                scanf("%d%d",&l,&r);
                for(int j=0;j<top;j++){
                        ans+=
                        C(r-L[j]+tot-cnt[j]+1,tot-cnt[j]+1)*val[j]%mod
                        +C(r-R[j]-1+tot-cnt[j]+1,tot-cnt[j]+1)*(-val[j])%mod
                        -C(l-1-L[j]+tot-cnt[j]+1,tot-cnt[j]+1)*val[j]%mod
                        -C(l-1-R[j]-1+tot-cnt[j]+1,tot-cnt[j]+1)*(-val[j])%mod;
                    ((ans%=mod)+=mod)%=mod;
                }
                cout<<ans<<endl;
            }
        }
    }
    return 0;
}
View Code

Rikka with Equation

Rikka with Line Graph

Rikka with Shortest Path

Rikka with Ants

Rikka with Zombies

Rikka with Nickname

思路:记录下每个字母的位置,然后合并时查找第一个可行的位置,然后更新可行区间。

队友代码:

#include<bits/stdc++.h>
using namespace std;
int idx(char c){
    return c-'a';
}
vector<int> pos[26];
int getPos(int id,int p){
    if(lower_bound(pos[id].begin(),pos[id].end(),p)==pos[id].end())return -1;
    else return pos[id][lower_bound(pos[id].begin(),pos[id].end(),p)-pos[id].begin()];
}
void init(){
    for(int i=0;i<26;i++)pos[i].clear();
}
char ans[1000010];
char s[1000010];
int main(){
    int T,n,m;
    scanf("%d",&T);
    for(int t=1;t<=T;t++){
        scanf("%d",&n);
        int tot=0;
        init();
        for(int i=1;i<=n;i++){
            scanf("%s",s);
            m=strlen(s);
            int ppos=0;
            for(int j=0;j<m;j++){
                if(ppos==-1){
                    pos[idx(s[j])].push_back(tot);
                    ans[tot++]=s[j];
                }
                else{
                    ppos=(getPos(idx(s[j]),ppos));
                    if(ppos==-1){
                        pos[idx(s[j])].push_back(tot);
                        ans[tot++]=s[j];
                    }
                    else{
                        ppos++;
                    }
                }
            }
        }
        ans[tot]=0;
        puts(ans);
    }
    return 0;
}
View Code
posted @ 2018-08-03 20:03  Wisdom+.+  阅读(998)  评论(0编辑  收藏  举报