2019暑期多校

咕值詳見去年多校php

牛客html

2019牛客暑期多校訓練營(第一場)java

題號 標題 團隊的狀態
A Equivalent Prefixes  經過
B Integration  經過
C Euclidean Distance  經過
D Parity of Tuples 未經過
E ABBA  經過
F Random Point in Triangle  經過
G Substrings 2 未經過
H XOR  經過
I Points Division  經過
J Fraction Comparision  經過

Anode

思路:二分+單調棧ios

代碼:c++

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
const int N = 1e5 + 5;
int n, a[N], b[N], la[N], ra[N],lb[N], rb[N];
stack<int> st;
inline bool ck(int m) {
    while(!st.empty()) st.pop();
    st.push(0);
    for (int i = 1; i <= m; ++i) {
        while(!st.size() > 1 && a[st.top()] > a[i]) st.pop();
        la[i] = st.top();
        st.push(i);
    }
    while(!st.empty()) st.pop();
    st.push(m+1);
    for (int i = m; i >= 1; --i) {
        while(st.size() > 1 && a[st.top()] > a[i]) st.pop();
        ra[i] = st.top();
        st.push(i);
    }
 
    while(!st.empty()) st.pop();
    st.push(0);
    for (int i = 1; i <= m; ++i) {
        while(!st.size() > 1 && b[st.top()] > b[i]) st.pop();
        lb[i] = st.top();
        st.push(i);
    }
    while(!st.empty()) st.pop();
    st.push(m+1);
    for (int i = m; i >= 1; --i) {
        while(st.size() > 1 && b[st.top()] > b[i]) st.pop();
        rb[i] = st.top();
        st.push(i);
    }
    for (int i = 1; i <= m; ++i) if(la[i] != lb[i] || ra[i] != rb[i]) return false;
    return true;
}
int main() {
    while(~scanf("%d", &n)) {
        for (int i = 1;  i <= n; ++i) scanf("%d", &a[i]);
        for (int i = 1;  i <= n; ++i) scanf("%d", &b[i]);
        int l = 1, r = n, m = l+r+1 >>1;
        while( l < r) {
            if(ck(m)) l = m;
            else r = m-1;
            m = l+r+1>>1;
        }
        printf("%d\n", m);
    }
    return 0;
}
View Code

Bgit

思路:裂項,詳見D神博客數組

代碼:bash

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
const int N = 1e3 + 5;
const int MOD = 1e9 + 7;
int a[N], 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() {
    while(~scanf("%d", &n)) {
        for (int i = 1; i <= n; ++i) scanf("%d",&a[i]);
        LL ans = 0;
        for (int i = 1; i <= n; ++i) {
            LL tmp = 2*a[i]%MOD;
            for (int j = 1; j <= n; ++j) {
                if(i == j) continue;
                tmp = (tmp * (a[j]*1LL*a[j]%MOD-a[i]*1LL*a[i]%MOD))%MOD;
            }
            ans = (ans + q_pow(tmp, MOD-2))%MOD;
        }
        printf("%lld\n", (ans+MOD)%MOD);
    }
    return 0;
}
View Code

Capp

思路:貪心,從大到小推平。詳見大佬博客

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
const int N = 1e4 + 5;
int a[N], sum[N], n, m;
int main() {
    while(~scanf("%d %d", &n, &m)) {
        for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
        sort(a+1, a+1+n, greater<int>());
        for (int i = 1; i <= n; ++i) sum[i] = sum[i-1]+a[i];
        int pos = n+1;
        LL x=0, y=0;
        for (int i = 1; i <= n; ++i){
            if(sum[i]-a[i]*i <= m) {
                x = (sum[i]-m)*1LL*(sum[i]-m)*i;
                y = i*i;
            }
            else {
                pos = i;
                break;
            }
        }
        for (int i = pos; i <= n; ++i) x += a[i]*1LL*a[i]*y;
        y *= m*m;
        LL d = __gcd(x, y);
        if(d) x /= d, y /= d;
        if(x == 0) printf("0\n");
        else if(y == 1) printf("%lld\n", x);
        else printf("%lld/%lld\n", x, y);
    }
    return 0;
}
View Code

D

E

思路:dp,保證A和B的差值在$-m$到$+n$之間

代碼:

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)
 
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
 
 
template<class T> void _R(T &x) { cin >> x; }
void _R(int &x) { scanf("%d", &x); }
void _R(ll &x) { scanf("%lld", &x); }
void _R(double &x) { scanf("%lf", &x); }
void _R(char &x) { scanf(" %c", &x); }
void _R(char *x) { scanf("%s", x); }
void R() {}
template<class T, class... U> void R(T &head, U &... tail) { _R(head); R(tail...); }
 
 
template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}
 
const int inf = 0x3f3f3f3f;
 
const int mod = 1e9+7;
 
/**********showtime************/
            const int maxn = 8e3+9;
            ll dp[maxn][maxn];
            int g(int x) {
                return x + 4000;
            }
int main(){
            int n,m;
            while(~scanf("%d%d", &n, &m)) {
                int s = 2 * (n + m);
                int t = (n + m);
                for(int i=0; i<=s; i++) {
                    for(int j=-t; j<=t; j++) {
                        dp[i][g(j)] = 0;
                    }
                }
 
                dp[0][g(0)] = 1;
 
                for(int i=1; i<=s; i++) {
                    for(int j=-t; j<=t; j++) {
                        if(j <= n)
                            dp[i][g(j)] = (dp[i][g(j)] + dp[i-1][g(j-1)] ) %mod;
                        if(j >= -m)
                            dp[i][g(j)] = (dp[i][g(j)] + dp[i-1][g(j+1)] ) %mod;
                    }
                }
//                cout<<dp[s][g(0)]<<endl;
                printf("%lld\n", dp[s][g(0)]);
            }
            return 0;
}
View Code

F

思路:

$\frac{22*s}{36}$

代碼:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
 
struct Point  {   // double pan duan
    ll  x,y;
    Point(ll a=0,ll b=0) { x=a;y=b; };
};
typedef Point Vector;
Vector operator + (Vector A, Vector B){ return Vector(A.x+B.x, A.y+B.y); } // 向量相加
Vector operator - (Point  A, Point  B){ return Vector(A.x-B.x, A.y-B.y); } // 向量生成
double operator * (Vector A, Vector B){ return A.x*B.x-A.y*B.y;          } // 點積
double operator ^ (Vector A, Vector B){ return A.x*B.y-A.y*B.x;          } // 叉積
ll Cross(Vector A, Vector B)        { return A.x*B.y - A.y*B.x;                             }  // 叉積
ll Area2(Point A, Point B, Point C) { return Cross(B-A, C-A);                               }  // 四邊形面積
int main(){
   Point a,b,c;
   while(~scanf("%lld %lld %lld %lld %lld %lld",&a.x,&a.y,&b.x,&b.y,&c.x,&c.y)){
      ll area=abs(Cross(b-a,c-a) ) *11;
      printf("%lld\n",area);
   }
}
View Code

G

H

思路:線性基。

先將問題轉換成包含某個元素的異或起來爲0的集合個數和

首先,先選出一組基(假設大小爲$r$),那麼對於非基元素的任意組合均可由基線性表示,也就是說對於每一個非基元素,有$2^{n-r-1}$個包含它的集合知足題意,

這部分貢獻是$(n-r)*2^{n-r-1}$。

而後考慮包含基元素的知足題意的集合個數,對於某個基元素,將剩下的$n-1$個元素構成一組基,看能不能線性表示出它,若是能,包含這個基元素的集合個數是$2^{剩下元素個數}$

對於第二種狀況能夠先處理出非基元素的一組基。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 1e5 + 5;
const int MOD = 1e9 + 7;
int n;
LL a[N];
vector<LL> s, b, other, B; 
LL q_pow(LL n, LL k) {
    if(k < 0) return 0;
    LL res = 1;
    while(k) {
        if(k&1) res = (res*n)%MOD;
        n = (n*n)%MOD;
        k >>= 1;
    }
    return res;
}
int main() {
    while(~scanf("%d", &n)) {
        s.clear();b.clear();other.clear();B.clear();
        for (int i = 1; i <= n; ++i) scanf("%lld", &a[i]);
        for (int i = 1; i <= n; ++i) {
            LL t = a[i];
            for (LL x : b) {
                if((t^x) < t) t ^= x;
            }
            if(t) b.pb(t), s.pb(a[i]);
            else other.pb(a[i]);
        } 
        int sz = b.size();
        LL ans = (n-sz)*q_pow(2, n-sz-1)%MOD;
        for (LL x : other) {
            for (LL t : B) {
                if((x^t) < x) x ^= t;
            }
            if(x) B.pb(x);
        }
        for (LL x : s) {
            vector<LL> tb = B;
            for (LL t : s) {
                if(t != x) {
                    for (LL y : tb) {
                        if((y^t) < t) t ^= y;
                    }
                    if(t) tb.pb(t);
                }
            }
            for (LL t : tb) {
                if((x^t) < x) x ^= t;
            }
            if(!x) ans = (ans + q_pow(2, n-tb.size()-1))%MOD;
        }
        printf("%lld\n", ans);
    }
    return 0;
} 
View Code

I

思路:線段樹優化dp。

首先根據題意,A和B集合的分界線確定是一橫一豎交替出現的折線。那麼考慮以每一個點i爲折線的轉折點時的dp[i]。用線段樹維護以前轉折點的最大值並更新以當前點爲轉折點的最大值。

對於每一個點i,它對y值爲[0, a[i].y-1]轉折點的貢獻爲a,對y值爲[a[i].y+1,len]轉折點的貢獻爲b。由於a集合在上,b集合在下。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
const int N = 1e5 + 5;
struct Node {
    int x, y, a, b;
    bool operator < (const Node & rhs) const {
        if(x == rhs.x) return y > rhs.y;
        else return x < rhs.x;
    }
}a[N];
int n;
vector<int> vc;
LL mx[N<<2], lazy[N<<2];
inline void push_up(int rt) {
    mx[rt] = max(mx[rt<<1], mx[rt<<1|1]);
}
inline void push_down(int rt) {
    lazy[rt<<1] += lazy[rt];
    lazy[rt<<1|1] += lazy[rt];
    mx[rt<<1] += lazy[rt];
    mx[rt<<1|1] += lazy[rt];
    lazy[rt] = 0;
}
void build(int rt, int l, int r) {
    mx[rt] = lazy[rt] = 0;
    if(l == r) return ;
    int m = l+r >> 1;
    build(ls);
    build(rs);
    push_up(rt);
}
void update(int p, LL v, int rt, int l, int r) {
    if(l == r){
        mx[rt] = v;
        return ;
    }
    int m = l+r >> 1;
    if(lazy[rt]) push_down(rt);
    if(p <= m) update(p, v, ls);
    else update(p, v, rs);
    push_up(rt);
}
void Update(int L, int R, int v, int rt, int l, int r) {
    if(L > R) return ;
    if(L <= l && r <= R) {
        mx[rt] += v;
        lazy[rt] += v;
        return ;
    }
    int m = l+r >> 1;
    if(lazy[rt]) push_down(rt);
    if(L <= m) Update(L, R, v, ls);
    if(R > m)  Update(L, R, v, rs);
    push_up(rt);
}
LL query(int L, int R, int rt, int l, int r){
    if(L > R) return 0;
    if(L <= l && r <= R) return mx[rt];
    int m = l+r >> 1;
    if(lazy[rt]) push_down(rt);
    LL ans = 0;
    if(L <= m) ans = max(ans, query(L, R, ls));
    if(R > m) ans = max(ans, query(L, R, rs));
    push_up(rt);
    return ans;
}
int main() {
    while(~scanf("%d", &n)) {
        vc.clear();
        for (int i = 1; i <= n; ++i) scanf("%d %d %d %d",&a[i].x, &a[i].y, &a[i].a, &a[i].b), vc.pb(a[i].y);
        sort(vc.begin(), vc.end());
        vc.erase(unique(vc.begin(), vc.end()), vc.end());
        for (int i = 1; i <= n; ++i) a[i].y = lower_bound(vc.begin(), vc.end(), a[i].y)-vc.begin()+1;
        sort(a+1, a+1+n);
        int l = vc.size();
        ++l;
        build(1, 0, l);
        for (int i = 1; i <= n; ++i) {
            LL tmp = query(0, a[i].y, 1, 0, l);
            update(a[i].y, tmp+a[i].b, 1, 0, l);
            Update(0, a[i].y-1, a[i].a, 1, 0, l);
            Update(a[i].y+1, l, a[i].b, 1, 0, l);
        }
        printf("%lld\n", mx[1]);
    }
    return 0;
}
/*
3
1 1 10 1
8 9 10 1
5 4 10 1
*/
View Code

J

思路:大數過

import java.math.BigInteger;
import java.util.*;
 
public class Main {
 
    /**
     * @param args
     */
     
    public static void main(String[] args) {
            BigInteger x, a, y, b;
            Scanner reader = new Scanner(System.in);
            while(reader.hasNext()) {
                x = reader.nextBigInteger();
                a = reader.nextBigInteger();
                y = reader.nextBigInteger();
                b = reader.nextBigInteger();
                if(x.multiply(b).compareTo(y.multiply(a)) == 0) {
                    System.out.println("=");
                }
                else if(x.multiply(b).compareTo(y.multiply(a)) > 0)  {
                    System.out.println(">");
                }
                else {
                    System.out.println("<");
                }
            }
                 
        }
 
}
View Code

2019牛客暑期多校訓練營(第二場)

題號 標題 團隊的狀態
A Eddy Walker  經過
B Eddy Walker 2  經過
C Go on Strike! 未經過
D Kth Minimum Clique  經過
E MAZE  經過
F Partition problem  經過
G Polygons  經過
H Second Large Rectangle  經過
I Inside A Rectangle 未經過
J Subarray  經過

A

思路:蒙特卡洛一下,就能找到規律,除了0這個點,其餘點的機率是$\frac{1}{n-1}$,隊友讀了題竟然沒跟我說題意,血虧。

以n=10爲例,打表代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back

int  a[10];
int main() {
    mt19937 mt_rand(time(NULL));
    for (int i = 1; i <= 100000; ++i) {
        int st = 0;
        int up = 1<<10, s = 1;
        while(true) {
            if(mt_rand()%2 == 0) st = (st+9)%10;
            else st = (st+1)%10;
            s |= 1<< st;
            if(s == up-1) {
                a[st]++;
                break;
            }
        }
    }
    for (int i = 0; i < 10; ++i) printf("%d %.10f\n", i, a[i]*1.0/100000);
    return 0;
}
View Code

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pb push_back
 
const int MOD = 1e9 + 7;
int T, m, n;
LL q_pow(LL n, LL k) {
    LL res = 1;
    while(k) {
        if(k&1) res = (res*n) % MOD;
        n = (n * n)%MOD;
        k >>= 1;
    }
    return res;
}
int main() {
    scanf("%d", &T);
    LL res = 1;
    while(T--) {
        scanf("%d %d", &n, &m);
        if(n == 1) ;
        else if(m) (res *= q_pow(n-1, MOD-2)) %= MOD;
        else res *= 0;
        printf("%lld\n", res);
    }
    return 0;
}
View Code

B

思路:容易發現是個線性遞推式,由於係數$\frac{1}{k}$是個常數。因而能夠打出前2*k項,扔進杜教BM板子裏就能求出第$n$項。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
 
const int mod = 1e9 + 7;
const int MOD = 1e9 + 7;
ll q_pow(ll n, ll k) {
    ll res = 1;
    while(k) {
        if(k&1) res = (res*n)%mod;
        n = (n*n)%mod;
        k >>= 1;
    }
    return res;
}
 
namespace linear_seq {
    const int N=10010;
    #define rep(i,a,n) for (int i=a;i<n;i++)
    #define per(i,a,n) for (int i=n-1;i>=a;i--)
    #define mp make_pair
    #define all(x) (x).begin(),(x).end()
    #define SZ(x) ((int)(x).size())
    typedef vector<ll> VI;
    typedef pair<ll,ll> PII;
    ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
    ll res[N],base[N],_c[N],_md[N];
    vector<ll> Md;
    void mul(ll *a,ll *b,int k) {
        rep(i,0,k+k) _c[i]=0;
        rep(i,0,k) if (a[i]) rep(j,0,k) _c[i+j]=(_c[i+j]+a[i]*b[j])%mod;
        for (int i=k+k-1;i>=k;i--) if (_c[i])
            rep(j,0,SZ(Md)) _c[i-k+Md[j]]=(_c[i-k+Md[j]]-_c[i]*_md[Md[j]])%mod;
        rep(i,0,k) a[i]=_c[i];
    }
    ll solve(ll n,VI a,VI b) { // a 係數 b 初值 b[n+1]=a[0]*b[n]+...
//        printf("%d\n",SZ(b));
        ll ans=0,pnt=0;
        int k=SZ(a);
        assert(SZ(a)==SZ(b));
        rep(i,0,k) _md[k-1-i]=-a[i];_md[k]=1;
        Md.clear();
        rep(i,0,k) if (_md[i]!=0) Md.push_back(i);
        rep(i,0,k) res[i]=base[i]=0;
        res[0]=1;
        while ((1ll<<pnt)<=n) pnt++;
        for (int p=pnt;p>=0;p--) {
            mul(res,res,k);
            if ((n>>p)&1) {
                for (int i=k-1;i>=0;i--) res[i+1]=res[i];res[0]=0;
                rep(j,0,SZ(Md)) res[Md[j]]=(res[Md[j]]-res[k]*_md[Md[j]])%mod;
            }
        }
        rep(i,0,k) ans=(ans+res[i]*b[i])%mod;
        if (ans<0) ans+=mod;
        return ans;
    }
    VI BM(VI s) {
        VI C(1,1),B(1,1);
        int L=0,m=1,b=1;
        rep(n,0,SZ(s)) {
            ll d=0;
            rep(i,0,L+1) d=(d+(ll)C[i]*s[n-i])%mod;
            if (d==0) ++m;
            else if (2*L<=n) {
                VI T=C;
                ll c=mod-d*powmod(b,mod-2)%mod;
                while (SZ(C)<SZ(B)+m) C.pb(0);
                rep(i,0,SZ(B)) C[i+m]=(C[i+m]+c*B[i])%mod;
                L=n+1-L; B=T; b=d; m=1;
            } else {
                ll c=mod-d*powmod(b,mod-2)%mod;
                while (SZ(C)<SZ(B)+m) C.pb(0);
                rep(i,0,SZ(B)) C[i+m]=(C[i+m]+c*B[i])%mod;
                ++m;
            }
        }
        return C;
    }
    ll gao(VI a,ll n) {
        VI c=BM(a);
        c.erase(c.begin());
        rep(i,0,SZ(c)) c[i]=(mod-c[i])%mod;
        return solve(n,c,VI(a.begin(),a.begin()+SZ(c)));
    }
};
int k, T;
ll n;
int main() {
    scanf("%d", &T);
    while(T--) {
        scanf("%d %lld", &k, &n);
        vector<ll> vc;
        if(n == -1) printf("%lld\n", 2*q_pow(k+1, MOD-2)%MOD);
        else {
            vc.pb(1);
            for (int i = 1; i <= 2*k; ++i) {
                ll tmp = 0;
                for (int j = max(0, i-k); j < i; ++j){
                    (tmp += vc[j]) %= MOD;
                }
                (tmp *= q_pow(k, MOD-2)) %= MOD;
                vc.pb(tmp);
            }
            printf("%lld\n", linear_seq::gao(vc, n));
        }
    }
    return 0;
}
View Code

C

D

思路:

既然要選擇第K小的,咱們能夠從小到大作。每次經過最小的一個最小團擴展,能夠利用bitset優化判斷擴展的可行性。利用優先隊列,從其中取出的第k個就是答案。

隊友代碼:

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)
 
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
 
 
template<class T> void _R(T &x) { cin >> x; }
void _R(int &x) { scanf("%d", &x); }
void _R(ll &x) { scanf("%lld", &x); }
void _R(double &x) { scanf("%lf", &x); }
void _R(char &x) { scanf(" %c", &x); }
void _R(char *x) { scanf("%s", x); }
void R() {}
template<class T, class... U> void R(T &head, U &... tail) { _R(head); R(tail...); }
 
 
template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}
 
const int inf = 0x3f3f3f3f;
 
const int mod = 1e9+7;
 
/**********showtime************/
 
            const int maxn = 109;
            char str[maxn];
            struct node{
                ll val;
                bitset<109>bs;
                bool operator<(const node & o) const{
                    return val > o.val;
                }
            }a[maxn];
int main(){
            int n,k;
            scanf("%d%d", &n, &k);
            for(int i=1; i<=n; i++) {
                scanf("%lld", &a[i].val);
            }
            for(int i=1; i<=n; i++) {
                scanf("%s", str+1);
                for(int j=1; j<=n; j++) {
                    if(str[j] == '1')a[i].bs.set(j);
                }
            } 
 
            priority_queue<node>que;
            node s;
            s.val = 0;
            s.bs.reset();
            que.push(s);
            int flag = 0;ll res;
            while(!que.empty()) {
                node u = que.top();
                que.pop();
                k -- ;
                if(k == 0) {
                    flag = 1;
                    res = u.val;
                    break;
                }
                int mx = 1;
                for(int i=1; i<=n; i++) {
                    if(u.bs[i] == 1) mx = i + 1;
                }
 
                for(int i=mx; i<=n; i++) {
                    if((u.bs & a[i].bs) == u.bs) {
                        u.bs.set(i);    u.val += a[i].val;
                        que.push(u);
                        u.bs.reset(i);    u.val -= a[i].val;
                    }
                }
            }
            if(flag) printf("%lld\n", res);
            else puts("-1");
            return 0;
}
View Code

E

思路:

考慮從第$i$行到第$i+1$行的轉移,假設第$i$行爲"10010"

設 $dp_{i,j}$表示到第$i$行第$j$列的方案數。

因而相鄰兩項dp的轉移過程能夠當作一個矩陣乘以一個向量(若是暫時不考慮當前行的橫向轉移)。 多項之間的轉移能夠當作矩陣連乘再乘以一個向量。

因而用線段樹維護矩陣的乘法,線段樹每一個葉子節點表示一個矩陣。 單次修改複雜度O($log(n)m^3$),其中$m^3$是矩陣乘法的複雜度。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
const int N = 5e4 + 5;
const int MOD = 1e9 + 7;
int n, q, m, op, x, y;
string b[N];
struct Matrix {
    int a[10][10];
    inline void init() {memset(a, 0, sizeof a);}
    inline void _init() {
        init();
        for (int i = 0; i < m; ++i) a[i][i] = 1;
    }
    inline void reset(int p) {
        init();
        for (int i = 0; i < m; ++i) {
            for (int j = i; j >= 0; --j) if(b[p][j] == '0') a[j][i] = 1; else break;
            for (int j = i; j < m; ++j) if(b[p][j] == '0') a[j][i] = 1; else break;
        }
    }
    inline Matrix operator * (const Matrix & rhs) const {
        Matrix res;
        res.init();
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < m; ++j) {
                if(a[i][j]) {
                    for (int k = 0; k < m; ++k) (res.a[i][k] += a[i][j]*1LL*rhs.a[j][k]%MOD) %= MOD;
                }
            }
        }
        return res;
    }
}tree[N<<2];
inline void push_up(int rt) {
    tree[rt] = tree[rt<<1]*tree[rt<<1|1];
}
void build(int rt, int l, int r) {
    if(l == r) {
        tree[rt].reset(l);
        return ;
    }
    int m = l+r >> 1;
    build(ls);
    build(rs);
    push_up(rt);
}
void update(int p, int rt, int l, int r) {
    if(l == r) {
        tree[rt].reset(l);
        return ;
    }
    int m = l+r >> 1;
    if(p <= m) update(p, ls);
    else update(p, rs);
    push_up(rt);
}
 
int main(){
    fio;
    cin >> n >> m >> q;
    for (int i = 1; i <= n; ++i) cin >> b[i];
    build(1, 1, n);
    while(q--) {
        cin >> op >> x >> y;
        if(op == 1) {
            if(b[x][y-1] == '1') b[x][y-1] = '0'; else b[x][y-1] = '1';
            update(x, 1, 1, n);
        }
        else {
            cout << tree[1].a[x-1][y-1] << "\n";
        }
    }
    return 0;
}
View Code

F

思路:折半枚舉,對於每一半的每一個狀態記錄每一行狀態爲1的行和,最後暴力更新答案。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pb push_back
const int manx=1e6+10;
int n;
int a[30][30];
LL mp[(1<<15)][30];
LL mq[(1<<15)][30];
vector<int> vc[18];
int main(){
    scanf("%d",&n);
    for(int i=0;i<2*n;i++){
        for(int j=0;j<2*n;j++){
            scanf("%d",&a[i][j]);
        }
    }
    int up = 1<<n;
    for(int i=0;i<up;i++){
        for(int j=0;j<n;j++){
            if(i&(1<<j)){
                for (int k = 0; k < 2*n; ++k) {
                    mp[i][k] += a[k][j];
                }
            }
        }
    }
    for(int i=0;i<up;i++){
        for(int j=0;j<n;j++){
            if(i&(1<<j)){
                for (int k = 0; k < 2*n; ++k) {
                    mq[i][k] += a[k][j+n];
                }
            }
        }
        vc[n-__builtin_popcount(i)].pb(i);
    }
    LL ans = 0;
    for (int i = 0; i < up; ++i) {
        int x = __builtin_popcount(i);
        for (int j : vc[x]){
            LL t = 0;
            for (int k = 0; k < n; ++k) {
                if((i&(1<<k)) == 0) t += mp[i][k]+mq[j][k];
                if((j&(1<<k)) == 0) t += mp[i][n+k]+mq[j][n+k];
            }
            ans = max(ans, t);
        }
    }
    printf("%lld\n", ans);
    return 0;
}
View Code

G

思路:平面直線圖模板題。

H

思路:將每一個最大面積和次大面積的左上角扔進map裏去重。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
const int N = 1e3 + 5;
int l[N][N], r[N][N], up[N][N], a[N][N], n, m;
char s[N][N];
map<int, vector<pii>, greater<int>> mp;
int main() {
    scanf("%d %d",&n, &m);
    for (int i = 1; i <= n; ++i) scanf("%s", s[i]+1);
    for (int i = 1; i <= n; ++i) for (int j = 1; j <= m; ++j) a[i][j] = s[i][j]-'0';
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            if(a[i][j]) l[i][j] = l[i][j-1]+1;
        }
        for (int j = m; j >= 1; --j) {
            if(a[i][j]) r[i][j] = r[i][j+1]+1;
        }
    }
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            if(a[i][j]) {
                up[i][j] = up[i-1][j]+1;
                if(a[i-1][j]) {
                    l[i][j] = min(l[i-1][j], l[i][j]);
                    r[i][j] = min(r[i-1][j], r[i][j]);
                }
                int A = up[i][j], B = r[i][j]+l[i][j]-1;
                mp[A*B].pb(i-up[i][j]+1, j-l[i][j]+1);
                mp[A*(B-1)].pb(i-up[i][j]+1, j-l[i][j]+1);
                mp[(A-1)*B].pb(i-up[i][j]+1, j-l[i][j]+1);
            }
        }
    }
    int t = 0;
    for (auto &it : mp) {
        sort(it.se.begin(), it.se.end());
        it.se.erase(unique(it.se.begin(), it.se.end()), it.se.end());
        for (int i = 0; i < it.se.size(); ++i) {
            ++t;
            if(t == 2) {
                printf("%d\n", it.fi);
                return 0;
            }
        }
    }
    printf("0\n");
    return 0;
}
View Code

I

J

思路:將每一個答案的區間包含的點扣出來而後求前綴和,詳見隊友博客

隊友代碼:

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;


template<class T> void _R(T &x) { cin >> x; }
void _R(int &x) { scanf("%d", &x); }
void _R(ll &x) { scanf("%lld", &x); }
void _R(double &x) { scanf("%lf", &x); }
void _R(char &x) { scanf(" %c", &x); }
void _R(char *x) { scanf("%s", x); }
void R() {}
template<class T, class... U> void R(T &head, U &... tail) { _R(head); R(tail...); }


template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}

const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;

/**********showtime************/
            const int maxm = 2e7+9;
            const int maxn = 1e6+9;
            int le[maxn],ri[maxn];
            int lto[maxn],rto[maxn];
            ll f[maxm];
            int g(int x) {
                return x + 10000000;
            }
int main(){
            int n;
            scanf("%d", &n);

            for(int i=1; i<=n; i++) scanf("%d%d", &le[i], &ri[i]);

            int sum = 0;
            /// 向右擴展
            le[n+1] = 1000000000;
            for(int i=1; i<=n; i++) {
                sum += ri[i] - le[i] + 1;
                rto[i] = min(sum, le[i+1] - ri[i] - 1);
                sum -= le[i+1] - ri[i] - 1;
                if(sum < 0) sum = 0;
            }
            /// 向左擴展
            sum = 0;
            ri[0] = -1;

            for(int i=n; i>=1; i--) {
                sum += ri[i] - le[i] + 1;
                lto[i] = min(sum , le[i] - ri[i-1] -1);
                sum -= le[i] - ri[i-1] - 1;
                if(sum < 0) sum = 0;
            }

            ///計算每一個點的前綴和。lowsum保存前綴和比當前點小的個數
            ll  ans = 0, lowsum = 0;
            int s = 0, pos = 0;
            f[g(0)] = 1;
            for(int i=1; i<=n; i++) {

                for(int j=max(pos, le[i] - lto[i]); j<=ri[i] + rto[i]; j++) {

                    if(j>=le[i] && j <= ri[i]) {
                        lowsum += f[g(s)];
                        s++;
                        f[g(s)]++;
                        ans += lowsum;
                    }
                    else {
                        s--;
                        lowsum -= f[g(s)];
                        f[g(s)]++;
                        ans += lowsum;
                    }
//                    cout<<j<<" "<<lowsum<<endl;
                    pos = j+1;
                }
            }
//            cout<<endl;
            printf("%lld\n", ans);
            return 0;
}
View Code

2019牛客暑期多校訓練營(第三場)

題號 標題 團隊的狀態
A Graph Games  經過
B Crazy Binary String  經過
C Guessing ETT 未經過
D Big Integer  經過
E Trees in the Pocket II 未經過
F Planting Trees  經過
G Removing Stones  經過
H Magic Line  經過
I Median  經過
J LRU management  經過

A

思路:將點按度數分紅兩種點,大於$\sqrt{m}$的稱爲大點,不然稱爲小點。而後再對邊分塊,修改邊的話,邊緣塊直接修改,整塊直接反轉。

而後還須要先預處理出每一個塊對大點的貢獻。對於每一個小點暴力查詢鏈接的每條邊是否反轉;對於每一個大點,考慮每一個塊是否反轉,並對它產生多少貢獻。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
   
struct FastIO {
    static const int S = 4e6;
    int wpos;
    char wbuf[S];
    FastIO() : wpos(0) {}
    inline int xchar() {
        static char buf[S];
        static int len = 0, pos = 0;
        if (pos == len)
            pos = 0, len = fread(buf, 1, S, stdin);
        if (pos == len) exit(0);
        return buf[pos++];
    }
    inline int xuint() {
        int c = xchar(), x = 0;
        while (c <= 32) c = xchar();
        for (; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0';
        return x;
    }
    inline int xint()
    {
        int s = 1, c = xchar(), x = 0;
        while (c <= 32) c = xchar();
        if (c == '-') s = -1, c = xchar();
        for (; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0';
        return x * s;
    }
    inline void xstring(char *s)
    {
        int c = xchar();
        while (c <= 32) c = xchar();
        for (; c > 32; c = xchar()) * s++ = c;
        *s = 0;
    }
    inline void wchar(int x)
    {
        if (wpos == S) fwrite(wbuf, 1, S, stdout), wpos = 0;
        wbuf[wpos++] = x;
    }
    inline void wint(int x)
    {
        if (x < 0) wchar('-'), x = -x;
        char s[24];
        int n = 0;
        while (x || !n) s[n++] = '0' + x % 10, x /= 10;
        while (n--) wchar(s[n]);
        wchar('\n');
    }
    inline void wstring(const char *s)
    {
        while (*s) wchar(*s++);
    }
    ~FastIO()
    {
        if (wpos) fwrite(wbuf, 1, wpos, stdout), wpos = 0;
    }
} io;
const int N = 1e5 + 5;
vector<int> g[N];
int T, n, m, d[N], u[N*2], v[N*2], op, l, r, q, id[N*2];
LL val[N], res[N], f[N][500];
bool ty[N];
struct BLOCK {
    int bl[N*2], block, blo[1000];
    inline void init() {
        for (int i = 1; i <= m; ++i) bl[i] = (i-1)/block + 1;
        for (int i = 1; i <= bl[m]; ++i) blo[i] = 0;
    }
    inline void update(int L, int R) {
        if(bl[L] == bl[R]) {
            for (int i = L; i <= R; ++i) res[u[i]] ^= val[v[i]], res[v[i]] ^= val[u[i]];
            return ;
        }
        for (int i = L; i <= bl[L]*block; ++i) res[u[i]] ^= val[v[i]], res[v[i]] ^= val[u[i]];
        for (int i = bl[L]+1; i <= bl[R]-1; ++i) blo[i] ^= 1;
        for (int i = (bl[R]-1)*block+1; i <= R; ++i) res[u[i]] ^= val[v[i]], res[v[i]] ^= val[u[i]];
     }
}b;
int main() {
    mt19937 mt_rand(time(NULL));
    T = io.xint();
    while(T--) {
        n = io.xint(); m = io.xint();
        for (int i = 1; i <= n; ++i) val[i] = mt_rand()%LONG_MAX;
        for (int i = 1; i <= m; ++i) u[i] = io.xint(), v[i] = io.xint(), g[u[i]].pb(i), g[v[i]].pb(i), d[u[i]]++, d[v[i]]++;
        int blo = sqrt(m)+1;
        b.block = blo;
        b.init();
        for (int i = 1; i <= n; ++i) {
            if(d[i] <= blo) ty[i] = 0;
            else ty[i] = 1;
        }
        for (int i = 1; i <= n; ++i) if(ty[i]) for (int j = 1; j <= b.bl[m]; ++j) f[i][j] = 0;
        for (int i = 1; i <= n; ++i) {
            for (int id : g[i]) {
                int y = u[id]^v[id]^i;
                res[i] ^= val[y];
                if(ty[i]) f[i][b.bl[id]] ^= val[y];
            }
        }
        q = io.xint();
        for (int i = 1; i <= q; ++i) {
            op = io.xint();
            l = io.xint();
            r = io.xint();
            if(op == 1) {
                b.update(l, r);
            }
            else {
                LL v1 = res[l], v2 = res[r];
                if(ty[l]) {for (int j = 1; j <= b.bl[m]; ++j) if(b.blo[j]) v1 ^= f[l][j];}
                else for (int id : g[l]) if(b.blo[b.bl[id]]) v1 ^= val[u[id]^v[id]^l];
                if(ty[r]) {for (int j = 1; j <= b.bl[m]; ++j) if(b.blo[j]) v2 ^= f[r][j];}
                else for (int id : g[r]) if(b.blo[b.bl[id]]) v2 ^= val[u[id]^v[id]^r];
                putchar((v1==v2)+'0');
            }
        }
        putchar('\n');
        for(int i = 1; i <= n; ++i) d[i] = 0, g[i].clear(), res[i] = 0;
        for (int i = 1; i <= m; ++i) id[i] = 0;
    }
    return 0;
}
View Code

B

思路:對於最長子段的計算,只要把0當作-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 = 1e5 + 10;
char s[N];
int n, sum[N], a, b, c1, c0;
map<int, int> mp;
int main() {
    scanf("%d", &n);
    scanf("%s", s+1);
    for (int i = 1; i <= n; ++i) if(s[i] == '1') c1++; else c0++;
    b = min(c1, c0)*2;
    mp[0] = 0;
    for (int i = 1; i <= n; ++i) {
        if(s[i] == '1') sum[i] = sum[i-1]+1;
        else sum[i] = sum[i-1]-1;
        if(mp.find(sum[i]) != mp.end()) a = max(a, i-mp[sum[i]]);
        else mp[sum[i]] = i;
    }
    printf("%d %d\n", a, b);
    return 0;
}
View Code

C

D

思路:首先有一個公式$\frac{x}{d}\%k = \frac{x\%k*d}{d}$。那麼原式$\frac{10^x-1}{9}\%p$能夠化簡$10^x = 1(\%(9*p))$。或者模數不乘$9$,但$p=3$時要特判。

當$p = 2, 5$時,答案確定是$0$。不然,求出最小的x知足等式,這個能夠用費馬小定理或者BSGS。而後就是求多少對$(i, j)$使得$x | i^j$。咱們先把$x$分解

質因數$x={p_1}^{a_1} {p_2}^{a_2}...{p_n}^{a_n}$,而後枚舉$j$,那麼對於一個固定的$j$,咱們發現$y = p_{1}^{\lceil\frac{a_{1}}{j}\rceil}p_{2}^{\lceil\frac{a_{2}}{j}\rceil}...p_{n}^{\lceil\frac{a_{n}}{j}\rceil} $的倍數的$j$次方必定是$x$的倍數, 那麼就是求小於$n$的數中有多少個是$y$的倍數。當$j \ge 30$時,$y$的質因子的冪次都變成了$1$。

代碼:

#include<bits/stdc++.h>
#define ll long long
#define LL long long
using namespace std;
LL qpow(LL n, LL k) {
    LL ans = 1;
    if(k == -1) return 0;
    while(k) {
        if(k&1) ans = (ans*n);
        n = (n*n);
        k >>= 1;
    }
    return ans;
}
unordered_map<int, int> mp;
LL q_pow(LL n, LL k, LL p) {
    LL ans = 1;
    if(k == -1) return 0;
    while(k) {
        if(k&1) ans = (ans*n) % p;
        n = (n*n) % p;
        k >>= 1;
    }
    return ans;
}
int BSGS(int a, int b, int p){
    int m = sqrt(p)+1, s = b;
    mp.clear();
    for(int i = 0; i < m; ++i){
        mp[s]=i;
        s= (s*1LL*a)%p;
    }
    int t = q_pow(a, m, p);
    s = 1;
    for(int i = 1; i <= m; ++i){
        s = (s*1LL*t)%p;
        if(mp.find(s) != mp.end()) return i*m-mp[s];
    }
    return -1;
}
int p,n,m;
vector<pair<int,int> > vs;
void make(int p){
    vs.clear();
    for(int i=2;i*i<=p;i++){
        if(p%i==0){
            int c=0;
            while(p%i==0){
                c++; p/=i;
            }
            vs.push_back({i,c});
        }
    }
    if(p!=1) vs.push_back({p,1});
    ll num=0;
    ll temp=1;
    for(int j=1;j<=min(30,m);j++){
        temp=1;
        for(int i=0; i<vs.size(); i++){
            temp=temp*qpow(vs[i].first,ceil(1.0*vs[i].second/j));
        }
        num+=n/temp;
    }
    if (m>30) num+=1ll*(m-30)*(n/temp);
    printf("%lld\n",num);
}
int main(){
    int T; scanf("%d",&T);
    while(T--){
        scanf("%d %d %d",&p,&n,&m);
        if(p==2 || p==5) { printf("0\n"); continue; }
        int x=BSGS(10,1,p);// cout<<x<<endl;
        if(p==3) x=3;
        make(x);
    }
}
View Code

E

F

思路:用枚舉上邊界l和下邊界r,先對於每一列求出最大值最小值,而後用單調隊列維護。這道題很卡常,有個用兩次單調隊列的$n^3$寫法被卡掉了。

代碼:

#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 = 505;
const int INF = 0x3f3f3f3f;
int a[N][N], mn[N], mx[N];
int q1[N*2], q2[N*2], T, n, m;
int main() {
    scanf("%d", &T);
    while(T--){
        scanf("%d %d", &n, &m);
        for (int i = 1; i <= n; ++i) for (int j = 1; j <= n; ++j) scanf("%d", &a[i][j]);
        int ans = 0;
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= n; ++j) mn[j] = INF, mx[j] = -INF;
            for (int j = i; j <= n; ++j) {
                for (int k = 1; k <= n; ++k) mn[k] = min(a[j][k], mn[k]), mx[k] = max(a[j][k], mx[k]);
                int le1 = N, ri1 = N-1;
                int le2 = N, ri2 = N-1;
                int pre = 0;
                for (int k = 1; k <= n; ++k) {
                    while(le1 <= ri1 && mn[q1[ri1]] >= mn[k]) ri1--;
                    q1[++ri1] = k;
                    while(le2 <= ri2 && mx[q2[ri2]] <= mx[k]) ri2--;
                    q2[++ri2] = k;
                    while(pre < k && mx[q2[le2]]-mn[q1[le1]] > m) {
                        ++pre;
                        while(le1 <= ri1 && q1[le1] <= pre) le1++;
                        while(le2 <= ri2 && q2[le2] <= pre) le2++;
                    }
                    if(pre < k && mx[q2[le2]] - mn[q1[le1]] <=m) ans = max(ans, (k - pre)*(j-i+1));
                }
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}
View Code

G

思路:分治,對於每一個分治的區間$[L,R]$,求出最大值的位置$p$,而後枚舉$[L,p]$或者$[p,R]$中小的區間中的每一個位置,而後找另外一個端點的位置。

而後遞歸區間$[L,p-1]$和區間$[p+1,R]$。時間複雜度$O(n*log(n))$

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 3e5 + 5;
int T, n, a[N], st[N][20], lg[N];
LL sum[N];
LL ans = 0;
inline void init() {
    for (int i = n; i >= 1; --i) {
        st[i][0] = i;
        for (int j = 1; i+(1<<j-1)-1 <= n; ++j) {
            if(a[st[i][j-1]] > a[st[i+(1<<j-1)][j-1]]) st[i][j] = st[i][j-1];
            else st[i][j] = st[i+(1<<j-1)][j-1];
        }
    }

}
inline int get_max(int L, int R) {
    int k = lg[R-L+1], x = st[L][k], y = st[R-(1<<k)+1][k];
    if(a[x] > a[y]) return x;
    else return y;
}
void solve(int L, int R) {
    if(L >= R) return ;
    int p = get_max(L, R);
    if(p-L < R-p) {
        int j = p;
        for (int i = L; i <= p; ++i) {
            while(j <= R && sum[j]-sum[i-1] < 2*a[p]) ++j;
            ans += R-j+1;
        }
    }
    else {
        int j = p;
        for (int i = R; i >= p; --i) {
            while(j >= L && sum[i]-sum[j==0?j:j-1] < 2*a[p]) --j;
            ans += j-L+1;
        }
    }
    solve(L, p-1);
    solve(p+1, R);
}
int main() {
    for (int i = 2; i < N; ++i) lg[i]=lg[i>>1]+1;
    scanf("%d", &T);
    while(T--) {
        scanf("%d", &n);
        for (int i = 1; i <= n; ++i) scanf("%d", &a[i]), sum[i] = sum[i-1]+a[i]; init();
        ans = 0;
        solve(1, n);
        printf("%lld\n", ans);
    }
    return 0;
}
View Code

H

思路:構造

代碼:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=2e3+10;
vector<int> vs[maxn];
int32_t main(){
    int T; scanf("%d",&T);
    while(T--){
        int n; scanf("%d",&n);
        for(int i=1;i<=n;i++){
           int x,y; scanf("%d %d",&x,&y); x+=1000; y+=1000;
           vs[x].push_back(y);
        }
        int temp=0;
        for(int i=0;i<=2000;i++){
            if(temp+vs[i].size()>=n/2){
                int d=n/2-temp;   sort(vs[i].begin(),vs[i].end());
                int y=vs[i][d-1];
                if(y>=1000){
                    int x1=i+1;     x1-=1000;
                    int y1=-1;      y1-=1000;
                    int x2=i+3;     x2-=1000;
                    int y2=-2*y-4;  y2-=1000;
                    printf("%d %d %d %d\n",x1,y1,x2,y2);
                }
                else {
                    int x1=i-1;
                    int y1=2001;
                    int x2=i-3;
                    int y2=-2*y+6003-1;
                    printf("%d %d %d %d\n",x1-1000,y1-1000,x2-1000,y2-1000);
 
                }
                break;
            }
            temp+=vs[i].size();
        }
        for(int i=0;i<=2000;i++) vs[i].clear();
    }
}
View Code

I

思路:若是能夠構造,那麼$a_i$必定能夠選擇$b_i,b_{i-1},b_{i-2}$中的一個值,具體證實看題解。那麼能夠想到一個狀態$dp[i][j][k]$,其中,$j$和$k$

分別表示$i$和$i-1$這兩個位置選擇的$b_i$和自己之間的距離,那判斷一下相鄰兩個之間的轉移可不可行就能夠轉移了。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 1e5 + 5;
bool dp[N][3][3];
int pre[N][3][3];
int T, n, b[N], a[N];
inline int ck(int x, int y, int z) {
    if(b[x] >= b[y] && b[x] >= b[z]) return max(b[y], b[z]);
    if(b[y] >= b[x] && b[y] >= b[z]) return max(b[x], b[z]);
    return max(b[x], b[y]);
}
int main() {
    scanf("%d", &T);
    while(T--) {
        scanf("%d", &n);
        for (int i = 1; i <= n-2; ++i) scanf("%d", &b[i]);
        if(n == 3) {
            for (int i = 1; i <= 3; ++i) printf("%d ", b[1]);
            printf("\n");
            continue;
        }
        for (int i = 1; i <= n; ++i) for (int j = 0; j < 3; ++j) for (int k = 0; k < 3; ++k) dp[i][j][k] = 0;
        for (int i = 1; i <= n; ++i) {
            if(i == 1) ;
            else if(i == 2) {
                for (int j = 0; j < 3; ++j) {
                    if(2-j < 1) break;
                    for (int k = 0; k < 3; ++k) {
                        if(1-k < 1) break;
                        dp[i][j][k] = 1;
                    }
                }
            }
            else {
                for (int j = 0; j < 3; ++j) {
                    for (int k = 0; k < 3; ++k) {
                        if(dp[i-1][j][k]) {
                            for (int l = 0; l < 3; ++l) {
                                if(i-l <= n-2) {
                                    if(ck(i-2-k, i-1-j, i-l) == b[i-2]) dp[i][l][j] = 1, pre[i][l][j] = k;
                                }
                            }
                        }
                    }
                }
            }
        }
        int x, y, z;
        bool f = false;
        for (int j = 0; j < 3; ++j) for (int k = 0; k < 3; ++k) if(dp[n][j][k]) {
            f = true;
            x = n; 
            y = j;
            z = k;
            break;
        }
        if(f) {
            while(x) {
                a[x] = b[x-y];
                int tmp = z;
                z = pre[x][y][z];
                y = tmp;
                x--;
            }    
            for (int i = 1; i <= n; ++i) printf("%d%c", a[i], " \n"[i==n]); 
        }
        else printf("-1\n");
    }
    return 0;
}
View Code

J

思路:用平衡樹維護,其實用set就能夠了,記錄一下每一個串最後的位置,若是這個串被刪除,也要記得刪除位置

代碼:

#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 + 10;
int ch[N][2], val[N], cnt[N], V[N], fa[N], sz[N], ncnt = 0, rt = 0;
string tmp[N];
inline int ck(int x) {
    return ch[fa[x]][1] == x;
}
inline void push_up(int x) {
    sz[x] = sz[ch[x][0]] + sz[ch[x][1]] + cnt[x];
}
void Rotate(int x) {
    int y = fa[x], z = fa[y];
    int k = ck(x), w = ch[x][k^1];
    ch[y][k] = w, fa[w] = y;
    ch[z][ck(y)] = x, fa[x] = z;
    ch[x][k^1] = y, fa[y] = x;
    push_up(y), push_up(x);
}
void Splay(int x, int goal = 0) {
    while(fa[x] != goal) {
        int y = fa[x], z = fa[y];
        if(z != goal) {
            if(ck(x) == ck(y)) Rotate(y);
            else Rotate(x);
        }
        Rotate(x);
    }
    if(!goal) rt = x;
}
void Find(int x) {
    if(!rt) return ;
    int cur = rt;
    while(ch[cur][x>val[cur]] && x != val[cur]) cur = ch[cur][x>val[cur]];
    Splay(cur);
}
void Insert(int x, int y, string s) {
    int cur = rt, p = 0;
    while(cur && val[cur] != x) {
        p = cur;
        cur = ch[cur][x>val[cur]];
    }
    if(cur) cnt[cur]++;
    else {
        cur = ++ncnt;
        if(p) ch[p][x>val[p]] = cur;
        fa[cur] = p;
        ch[cur][0] = ch[cur][1] = 0;
        val[cur] = x;
        V[cur] = y;
        tmp[cur] = s;
        cnt[cur] = sz[cur] = 1;
    }
    Splay(cur);
}
int Kth(int k) {
    int cur = rt;
    while(true) {
        if(ch[cur][0] && k <= sz[ch[cur][0]]) cur = ch[cur][0];
        else if(k > sz[ch[cur][0]] + cnt[cur]) k -=sz[ch[cur][0]] + cnt[cur], cur = ch[cur][1];
        else return cur;
    }
}
inline int get_min(int x) {
    while(x && ch[x][0]) x = ch[x][0];
    return x;
}
inline int get_max(int x) {
    while(x && ch[x][1]) x = ch[x][1];
    return x;
}
int Pre(int x) {
    Find(x);
    if(val[rt] < x) return rt;
    if(!ch[rt][0]) return -1;
    int cur = ch[rt][0];
    while(ch[cur][1]) cur = ch[cur][1];
    return cur;
}
int Succ(int x) {
    Find(x);
    if(val[rt] > x) return rt;
    if(!ch[rt][1]) return -1;
    int cur = ch[rt][1];
    while(ch[cur][0]) cur = ch[cur][0];
    return cur;
}
void Remove(int x) {
    int last = Pre(x), next = Succ(x);
    Splay(last), Splay(next, last);
    int del = ch[next][0];
    if(cnt[del] > 1) cnt[del]--, Splay(del);
    else ch[next][0] = 0, push_up(next), push_up(last);
}
void delete_root() {
    if(ch[rt][1]) {
        int cur = ch[rt][1];
        while(cur && ch[cur][0]) cur = ch[cur][0];
        Splay(cur, rt);
        ch[cur][0] = ch[rt][0];
        fa[ch[cur][0]] = cur;
        rt = cur;
    }
    else rt = ch[rt][0];
    fa[rt] = 0;
    if(rt) push_up(rt);
}
inline void init() {
    ncnt = rt = ch[0][0] = ch[0][1] = fa[0] = sz[0] = cnt[0] = val[0] = 0;
   // V[0] = -10;
}
int q, m, op, v, T;
string s;
unordered_map<string, int> mp;
int main() {
    fio;
    cin >> T;
    while(T--) {
        init();
        mp.clear();
        Insert(-1, -10, "0");
        Insert(N-1, -10, "0");
        cin >> q >> m;
        int now = 0;
        for (int i = 1; i <= q; ++i){
            cin >> op >> s >> v;
            int res = 0;
            if(op == 0) {
                 
                if(mp.find(s) == mp.end()) {
                    mp[s] = ++now;
                    Insert(now, v, s);
                    res = v;
                }
                else {
                    Find(mp[s]);
                    res = V[rt];
                    Remove(mp[s]);
                    mp[s] = ++now;
                    Insert(now, res, s);
                }
                cout << res << "\n";
            }
            else {
                if(mp.find(s) == mp.end()) {
                    cout << "Invalid\n";
                }
                else {
                    if(v == 0) {
                        Find(mp[s]);
                        cout <<  V[rt] << "\n";
                    }
                    else if(v == -1) {
                        int cur = Pre(mp[s]);
                        if(V[cur] == -10) cout << "Invalid\n";
                        else cout <<  V[cur] << "\n";
                    }
                    else {
                        int cur = Succ(mp[s]);
                        if(V[cur] == -10) cout << "Invalid\n";
                        else cout <<  V[cur] << "\n";
                    }
                }
            }
            if(sz[rt]-2 > m) {
                int cur = Kth(2);
                Splay(cur);
                delete_root();
                mp.erase(tmp[cur]);
            }
        }
    }
    return 0;
}
View Code

2019牛客暑期多校訓練營(第四場)

題號 標題 團隊的狀態
A meeting  經過
B xor  經過
C sequence  經過
D triples I  經過
E triples II  經過
F merge  經過
G tree 未經過
H RNGs 未經過
I string  經過
J free  經過
K number  經過

A

思路:虛樹直徑的一半。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
const int N = 1e5 + 5;
vector<int> g[N];
int a[N], sz[N], sum[N], n, k, u, v, s, mx;
void dfs(int u, int o, int d) {
    if(a[u]) {
        if(d > mx) {
            mx = d;
            s = u;
        }
    }
    for (int v : g[u]) {
        if(v != o){
            dfs(v, u, d+1);
        }
    }
}
int main() {
    scanf("%d %d", &n, &k);
    for (int i = 1; i < n; ++i) {
        scanf("%d %d", &u, &v);
        g[u].pb(v);
        g[v].pb(u);
    }
    for (int i = 1; i <= k; ++i) scanf("%d", &u), ++a[u];
    dfs(u, u, 0);
    dfs(s, s, 0);
    if(mx%2) printf("%d\n", (mx+1)/2);
    else printf("%d\n", mx/2);
    return 0;
}
View Code

B

思路:線性基求交+線段樹。建樹的複雜度是$O(n*32*32)$,查詢時不須要把須要查詢區間的交算出來,否則單次查詢複雜度$O(32*32*log(n))$,

只須要判斷這段區間在線段樹上的每一個節點是否是能夠表示$x$就能夠了,這樣單次查詢複雜度$O(32*log(n))$。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
  
const int N = 5e4 + 5;
struct LinearBase {
    LL v[32];
    inline void clr() {memset(v, 0, sizeof(v));}
    inline void ins(LL a) {
        for (int i = 31; i >= 0; --i) {
            if(a&(1LL<<i)) {
                if(!v[i]) {
                    v[i] = a;
                    break;
                }
                a ^= v[i];
            }
        }
    }
    inline bool can_ex(LL a) {
        for (int i = 31; i >= 0; --i) if((a^v[i]) < a)  a ^= v[i];
        return a == 0;
    }
    //
    inline friend LinearBase operator * (const LinearBase &a, const LinearBase &b) {
        LinearBase all, c, d;
        all.clr(), c.clr(), d.clr();
        for (int i = 31; i >= 0; --i) {
            all.v[i] = a.v[i];
            d.v[i] = 1LL<<i;
        }
        for (int i = 31; i >= 0; --i) {
            if(b.v[i]) {
                LL v = b.v[i], k = 0;
                bool can = true;
                for (int j = 31; j >= 0; --j) {
                    if(v&(1LL<<j)) {
                        if(all.v[j]) {
                            v ^= all.v[j];
                            k ^= d.v[j];
                        }
                        else {
                            can = false;
                            all.v[j] = v;
                            d.v[j] = k;
                            break;
                        }
                    }
                }
                if(can) {
                    LL v = 0;
                    for (int j = 31; j >= 0; --j) {
                        if(k&(1LL<<j)) {
                            v ^= a.v[j];
                        }
                    }
                    c.ins(v);
                }
            }
        }
        return c;
    }
}tree[N<<2];
vector<LL> vc[N];
inline void push_up(int rt) {
    tree[rt] = tree[rt<<1]*tree[rt<<1|1];
}
void build(int rt, int l, int r) {
    if(l == r) {
        tree[rt].clr();
        for (LL x : vc[l]) tree[rt].ins(x);
        return ;
    }
    int m = l+r >> 1;
    build(ls);
    build(rs);
    push_up(rt);
}
bool query(int L, int R, LL a, int rt, int l, int r) {
    if(L <= l && r <= R) return tree[rt].can_ex(a);
    int m = l+r >> 1;
    if(L <= m && m < R) return query(L, R, a, ls)&query(L, R, a, rs);
    if(L <= m) return query(L, R, a, ls);
    else return query(L, R, a, rs);
}
int n, m, t, l, r;
LL a;
int main() {
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &t);
        vc[i].resize(t);
        for (int j = 0; j < t; ++j) scanf("%lld", &vc[i][j]);
    }
    build(1, 1, n);
    while(m--) {
        scanf("%d %d %lld", &l, &r, &a);
        if(query(l, r, a, 1, 1, n)) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}
View Code

C

思路:南昌邀請賽原題。

先對b數組求個前綴和,而後用單調棧求出以每一個位置$p$爲最小值左端點的最左邊$L$和右端點的最右邊$R$。

若是$a[p] > 0$,用$max\left(sum[i], i\in[p, R]\right)- min\left(sum[i], i\in[L-1, p-1]\right)$;

若是$a[p] < 0$,用$min\left(sum[i], i\in[p, R]\right)- max\left(sum[i], i\in[L-1, p-1]\right)$。

方法一(單調棧+線段樹$O(nlog(n))2500ms$)

代碼:

#include <bits/stdc++.h>
 
using namespace std;
#define LL long long
#define fi first
#define se second
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
const int N = 3e6 + 5;
int a[N], b[N], pre[N], suf[N];
LL sum[N], mx[N<<2], mn[N<<2];
stack<int> st;
int n;
void push_up(int rt) {
    mn[rt] = min(mn[rt<<1], mn[rt<<1|1]);
    mx[rt] = max(mx[rt<<1], mx[rt<<1|1]);
}
void build(int rt, int l, int r) {
    if(l == r) {
        mx[rt] = mn[rt] = sum[l];
        return ;
    }
    int m = l+r >> 1;
    build(ls);
    build(rs);
    push_up(rt);
}
LL querymx(int L, int R, int rt, int l, int r) {
    if(L <= l && r <= R) return mx[rt];
    int m = l+r >> 1;
    LL ans = LONG_MIN;
    if(L <= m) ans = max(ans, querymx(L, R, ls));
    if(R > m) ans = max(ans, querymx(L, R, rs));
    return ans;
}
LL querymn(int L, int R, int rt, int l, int r) {
    if(L <= l && r <= R) return mn[rt];
    int m = l+r >> 1;
    LL ans = LONG_MAX;
    if(L <= m) ans = min(ans, querymn(L, R, ls));
    if(R > m) ans = min(ans, querymn(L, R, rs));
    return ans;
}
int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
    for (int i = 1; i <= n; ++i) scanf("%d", &b[i]);
    for (int i = 1; i <= n; ++i) sum[i] = sum[i-1] + b[i];
    build(1, 0, n);
    a[0] = a[n+1] = INT_MIN;
    st.push(0);
    for (int i = 1; i <= n; ++i) {
        while(!st.empty() && a[st.top()] >= a[i]) st.pop();
        pre[i] = st.top();
        st.push(i);
    }
    while(!st.empty()) st.pop();
    st.push(n+1);
    for (int i = n; i >= 1; --i) {
        while(!st.empty() && a[st.top()] >= a[i]) st.pop();
        suf[i] = st.top();
        st.push(i);
    }
    LL ans = -(1LL<<61);
    for (int i = 1; i <= n; ++i) {
        int l = pre[i], r = i-1;
        int ll = i, rr = suf[i]-1;
        if(a[i] < 0) {
            ans = max(ans, a[i]*(querymn(ll, rr, 1, 0, n)-querymx(l, r, 1, 0, n)));
        }
        else if(a[i] > 0) {
            ans = max(ans, a[i]*(querymx(ll, rr, 1, 0, n)-querymn(l, r, 1, 0, n)));
        }
    }
    printf("%lld\n", ans);
    return 0;
}
View Code

方法二(笛卡爾樹+快讀$O(n)350ms$,這個快讀優化了1200ms,出題人爲了卡$log$連讀入都卡掉了)

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

struct FastIO {
    static const int S = 4e6;
    int wpos;
    char wbuf[S];
    FastIO() : wpos(0) {}
    inline int xchar() {
        static char buf[S];
        static int len = 0, pos = 0;
        if (pos == len)
            pos = 0, len = fread(buf, 1, S, stdin);
        if (pos == len) exit(0);
        return buf[pos++];
    }
    inline int xuint() {
        int c = xchar(), x = 0;
        while (c <= 32) c = xchar();
        for (; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0';
        return x;
    }
    inline int xint()
    {
        int s = 1, c = xchar(), x = 0;
        while (c <= 32) c = xchar();
        if (c == '-') s = -1, c = xchar();
        for (; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0';
        return x * s;
    }
    inline void xstring(char *s)
    {
        int c = xchar();
        while (c <= 32) c = xchar();
        for (; c > 32; c = xchar()) * s++ = c;
        *s = 0;
    }
    inline void wchar(int x)
    {
        if (wpos == S) fwrite(wbuf, 1, S, stdout), wpos = 0;
        wbuf[wpos++] = x;
    }
    inline void wint(int x)
    {
        if (x < 0) wchar('-'), x = -x;
        char s[24];
        int n = 0;
        while (x || !n) s[n++] = '0' + x % 10, x /= 10;
        while (n--) wchar(s[n]);
        wchar('\n');
    }
    inline void wstring(const char *s)
    {
        while (*s) wchar(*s++);
    }
    ~FastIO()
    {
        if (wpos) fwrite(wbuf, 1, wpos, stdout), wpos = 0;
    }
} io;

const int N = 3e6 + 10;
struct Node {
    int id, key, par, ch[2];
    LL mxlf, mxri, mnlf, mnri;
    inline bool operator < (Node & rhs) {return id < rhs.id;}
    inline void init(int _id, int _key, int _par) {
        key = _key, id = _id, par = _par, ch[0] = ch[1] = 0;
    }
}tree[N];
inline int cartesian_build(int n) {
    for (int i = 1; i <= n; ++i) {
        int k = i-1;
        while(tree[k].key > tree[i].key) k = tree[k].par;
        tree[i].ch[0] = tree[k].ch[1];
        tree[tree[i].ch[0]].par = i;
        tree[k].ch[1] = i;
        tree[i].par = k;
    }
    return tree[0].ch[1];
}
LL ans = LONG_MIN, sum[N];
int n, a[N], b[N], rt;
inline void dfs(int u) {
    tree[u].mxlf = tree[u].mnlf =  sum[u-1];
    tree[u].mxri = tree[u].mnri = sum[u];
    if(tree[u].ch[0]) dfs(tree[u].ch[0]), tree[u].mxlf = max(tree[u].mxlf, tree[tree[u].ch[0]].mxlf), tree[u].mnlf = min(tree[u].mnlf, tree[tree[u].ch[0]].mnlf);
    if(tree[u].ch[1]) dfs(tree[u].ch[1]), tree[u].mxri = max(tree[u].mxri, tree[tree[u].ch[1]].mxri), tree[u].mnri = min(tree[u].mnri, tree[tree[u].ch[1]].mnri);
    if(tree[u].key > 0) ans = max(ans, tree[u].key*(tree[u].mxri-tree[u].mnlf));
    else ans = max(ans, tree[u].key*(tree[u].mnri-tree[u].mxlf));
    if(tree[u].ch[0]) tree[u].mxri = max(tree[u].mxri, tree[tree[u].ch[0]].mxri), tree[u].mnri = min(tree[u].mnri, tree[tree[u].ch[0]].mnri);
    if(tree[u].ch[1]) tree[u].mxlf = max(tree[u].mxlf, tree[tree[u].ch[1]].mxlf), tree[u].mnlf = min(tree[u].mnlf, tree[tree[u].ch[1]].mnlf);
}
int main() {
    n = io.xint();
    for (int i = 1; i <= n; ++i) a[i] = io.xint();
    tree[0].init(0, -1000001, 0);
    for (int i = 1; i <= n; ++i) b[i] = io.xint(), sum[i] = sum[i-1]+b[i], tree[i].init(i, a[i], 0);
    rt = cartesian_build(n);
    dfs(rt);
    printf("%lld\n", ans);
    return 0;
}
View Code

D

思路:$2^p\%3$:若是$p$是偶數,是1;若是$p$奇數,是2。

而後若是$a\%3==0$,答案就是自己;若是$a\% 3==1$,能夠取出一個偶數位或兩個奇數位,而後考慮怎把這些位和以前的位構成3的倍數;若是$a\%3==2$,同理。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
int T;
LL a;
vector<int> vc[2];
vector<LL> res;
int main() {
    scanf("%d", &T);
    while(T--) {
        vc[0].clear();
        vc[1].clear();
        res.clear();
        scanf("%lld", &a);
        for (int i = 0; i <= 61; ++i) {
            if(a&(1LL<<i)) vc[i%2].pb(i);
        }
        if(a%3 == 0) {
            res.pb(a);
        }
        else if(a%3 == 2) {
            bool f = false;
            if(vc[1].size() > 0) {
                if(vc[0].size() > 0) {
                    int x = vc[1][0], y = vc[0][0];
                    res.pb(a^(1LL<<x));
                    res.pb((1LL<<x)|(1LL<<y));
                    f = true;
                }
                if(vc[1].size() >= 3) {
                    int x = vc[1][0], y = vc[1][1], z = vc[1][2];
                    res.pb(a^(1LL<<x));
                    res.pb((1LL<<x)^(1LL<<y)^(1LL<<z));
                    f = true;
                }
            }
            if(!f && vc[0].size() >= 3) {
                int x = vc[0][0], y = vc[0][1], z = vc[0][2];
                res.pb(a^(1LL<<x)^(1LL<<y));
                res.pb((1LL<<x)^(1LL<<y)^(1LL<<z));
                f = true;
            }
 
        }
        else {
            bool f = false;
            if(vc[0].size() > 0) {
                if(vc[1].size() > 0) {
                    int x = vc[0][0], y = vc[1][0];
                    res.pb(a^(1LL<<x));
                    res.pb((1LL<<x)|(1LL<<y));
                    f = true;
                }
                if(vc[0].size() >= 3) {
                    int x = vc[0][0], y = vc[0][1], z = vc[0][2];
                    res.pb(a^(1LL<<x));
                    res.pb((1LL<<x)^(1LL<<y)^(1LL<<z));
                    f = true;
                }
            }
            if(!f && vc[1].size() >= 3) {
                int x = vc[1][0], y = vc[1][1], z = vc[1][2];
                res.pb(a^(1LL<<x)^(1LL<<y));
                res.pb((1LL<<x)^(1LL<<y)^(1LL<<z));
                f = true;
            }
        }
        printf("%d ", (int)res.size());
        //LL t = 0;
        for (int i = 0; i <res.size(); ++i) printf("%lld%c", res[i], " \n"[i+1==res.size()]);
        //cout << t << endl;
    }
    return 0;
}
View Code

E

思路:二維二項式反演。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
  
const int MOD = 998244353;
int T, c1, c2;
LL n, a, C[65][65], f[65][65];
inline LL q_pow(LL n, LL k) {
    LL res = 1;
    while(k) {
        if(k&1) res = (res*n)%MOD;
        n = (n*n)%MOD;
        k >>= 1;
    }
    return res;
}
inline void init() {
    C[0][0] = 1;
    for (int i = 1; i < 65; ++i) {
        C[i][0] = 1;
        for (int j = 1; j <= i; ++j) C[i][j] = (C[i-1][j]+C[i-1][j-1])%MOD;
    }
    for (int i = 0; i < 65; ++i) {
        for (int j = 0; j < 65; ++j) {
            for (int ii = 0; ii <= i; ++ii) {
                for (int jj = 0; jj <= j; ++jj) {
                    if((ii*1+jj*2)%3 == 0) {
                        (f[i][j] += C[i][ii]*C[j][jj]%MOD) %= MOD;
                    }
                }
            }
        }
    }
}
int main() {
    init();
    scanf("%d", &T);
    while(T--) {
        scanf("%lld %lld", &n, &a);
        c1 = c2 = 0;
        for (int i = 0; i <= 60; ++i) {
            if(a&(1LL<<i)) {
                if(i%2 == 0) ++c1;
                else ++c2;
            }
        }
        LL ans = 0;
        for (int i = 0; i <= c1; ++i) {
            for (int j = 0; j <= c2; ++j) {
                if((c1-i+c2-j)%2 == 0) (ans += C[c1][i]*C[c2][j]%MOD*q_pow(f[i][j], n)) %= MOD;
                else (ans -= C[c1][i]*C[c2][j]%MOD*q_pow(f[i][j], n)) %= MOD;
            }
        }
        ans = (ans + MOD) % MOD;
        printf("%lld\n", ans);
    }
    return 0;
}
View Code

F

思路:fhq treap。split操做換成按位置split。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head


struct fhq_treap {
    static const int N = 1e5 + 5;
    struct Node {
        int val, mx, key, lc, rc, sz;
    }tree[N];
    int rt, tot;
    inline void init() {
        rt = tot = 0;
        tree[rt].sz = tree[rt].val = tree[rt].mx = tree[rt].lc = tree[rt].rc = 0;
        srand(time(0));
    }
    inline void update(int rt) {
        tree[rt].mx = max(tree[rt].val, max(tree[tree[rt].lc].mx, tree[tree[rt].rc].mx));
        tree[rt].sz = tree[tree[rt].lc].sz + tree[tree[rt].rc].sz + 1;
    }
    void split(int rt, int &a, int &b, int x) {
        if(rt == 0) {a = b = 0; return ;}
        if(tree[tree[rt].lc].sz+1 <= x) {
            a = rt;
            split(tree[rt].rc, tree[a].rc, b, x-tree[tree[rt].lc].sz-1);
        }
        else {
            b = rt;
            split(tree[rt].lc, a, tree[b].lc, x);
        }
        update(rt);
    }
    void merge(int &rt, int a, int b) {
        if(a==0 || b==0) {
            rt = a+b;
            return ;
        }
        if(tree[a].key < tree[b].key) {
            rt = a;
            merge(tree[rt].rc, tree[a].rc, b);
        }
        else {
            rt = b;
            merge(tree[rt].lc, a, tree[b].lc);
        }
        update(rt);
    }
    inline int new_node() {
        tree[++tot].sz = 1;
        scanf("%d", &tree[tot].val);
        tree[tot].mx = tree[tot].val;
        tree[tot].lc = tree[tot].rc = 0;
        tree[tot].key = rand()*rand();
        return tot;
    }
    void ins(int &rt) {
        int node = new_node();
        merge(rt, rt, node);
    }
    void delete_node(int &rt, int val) {
        int x = 0, y = 0, z = 0;
        split(rt, x, y, val);
        split(x, x, z, val-1);
        merge(z, tree[z].lc, tree[z].rc);
        merge(x, x, z);
        merge(rt, x, y);
    }
    inline int get_kth(int rt, int k) {
        while(tree[tree[rt].lc].sz+1 != k) {
            if(tree[tree[rt].lc].sz >= k) rt = tree[rt].lc;
            else k -= tree[tree[rt].lc].sz+1, rt = tree[rt].rc;
        }
        return tree[rt].val;
    }
    int get_pos(int rt, int x) {
        if(!rt) return 0;
        if(tree[tree[rt].lc].mx > x) return get_pos(tree[rt].lc, x);
        else if(tree[rt].val > x) return tree[tree[rt].lc].sz;
        else return get_pos(tree[rt].rc, x)+tree[tree[rt].lc].sz+1;
    }
    int get_rnk(int &rt, int val) {
        int x = 0, y = 0;
        split(rt, x, y, val-1);
        int tmp = tree[x].sz+1;
        merge(rt, x, y);
        return tmp;
    }
    int get_pre(int &rt, int val) {
        int x = 0, y = 0;
        split(rt, x,  y, val-1);
        int tmp = get_kth(x, tree[x].sz);
        merge(rt, x, y);
        return tmp;
    }
    int get_scc(int &rt, int val) {
        int x = 0, y = 0;
        split(rt, x, y, val);
        int tmp = get_kth(y, 1);
        merge(rt, x, y);
        return tmp;
    }
}t;
void solve(int l, int m, int r) {
    int x = 0, y = 0;
    t.split(t.rt, x, y, r);
    t.rt = x;
    int a = 0, b = 0;
    t.split(t.rt, a, b, m);
    t.rt = 0;
    while(a&&b) {
        int va = t.get_kth(a, 1), vb = t.get_kth(b, 1);
        if(va > vb) swap(va, vb), swap(a, b);
        int p = t.get_pos(a, vb), tmp;
        t.split(a, tmp, a, p);
        t.merge(t.rt, t.rt, tmp);
    }
    if(a) t.merge(t.rt, t.rt, a);
    if(b) t.merge(t.rt, t.rt, b);
    t.merge(t.rt, t.rt, y);
}
int n, m, op, l, p, r;
int main() {
    t.init();
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; ++i) t.ins(t.rt);
    for (int i = 1; i <= m; ++i) {
        scanf("%d", &op);
        if(op == 1) {
            scanf("%d %d %d", &l, &p, &r);
            solve(l, p, r);
        }
        else {
            scanf("%d", &p);
            printf("%d\n", t.get_kth(t.rt, p));
        }
    }
    return 0;
}
View Code

G

H

I

思路:後綴數組+迴文自動機。

先將原串反轉放在原來的串的後面,用後綴數組求出本質不一樣的串的個數$a$,而後用迴文自動機求出本質不一樣的迴文串的個數$b$,而後$\frac{a+b}{2}$就是答案。

隊友的板子真醜。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
  
const int maxn=4e5+10;
char s[maxn];
int y[maxn],x[maxn],c[maxn],sa[maxn],rk[maxn],height[maxn];
int n,m,now,sz;
int get_sa()
{
    for (int i=0;i<=m;i++) c[i]=0;
    for (int i=1;i<=n;++i) ++c[x[i]=s[i]];
    for (int i=2;i<=m;++i) c[i]+=c[i-1];
    for (int i=n;i>=1;--i) sa[c[x[i]]--]=i;
    for (int k=1;k<=n;k<<=1)
    {
        int num=0;
        for (int i=n-k+1;i<=n;++i) y[++num]=i;
        for (int i=1;i<=n;++i) if (sa[i]>k) y[++num]=sa[i]-k;
        for (int i=1;i<=m;++i) c[i]=0;
        for (int i=1;i<=n;++i) ++c[x[i]];
        for (int i=2;i<=m;++i) c[i]+=c[i-1];
        for (int i=n;i>=1;--i) sa[c[x[y[i]]]--]=y[i],y[i]=0;
        swap(x,y);
        x[sa[1]]=1;num=1;
        for (int i=2;i<=n;++i)
        x[sa[i]]=(y[sa[i]]==y[sa[i-1]] && y[sa[i]+k]==y[sa[i-1]+k]) ? num : ++num;
        if (num==n) break;m=num;
    }
}
int get_height()
{
    int k=0;
    for (int i=1;i<=n;++i) rk[sa[i]]=i;
    for (int i=1;i<=n;++i)
    {
        if (rk[i]==1) continue;//第一名height爲0
        if (k) --k;//h[i]>=h[i-1]+1;
        int j=sa[rk[i]-1];
        while (j+k<=n && i+k<=n && s[i+k]==s[j+k]) ++k;
        height[rk[i]]=k;//h[i]=height[rk[i]];
    }
}
const double eps = 1E-8;
const int dx4[4]={1,0,0,-1};
const int dy4[4]={0,-1,1,0};
const int inf = 0x3f3f3f3f;
const int N=2e5+7;
struct PAM
{
    int fail,cnt,len;
    int nxt[26];
}st[N];
char RS[N];
string S;
  
void pam_init()
{
    mem(st,0);
    st[0].fail = st[1].fail = 1;
    st[1].len = -1;
    sz = 1;
}
void extend(int c,int pos)
{
    int p = now;
    while (S[pos-st[p].len-1]!=S[pos]) p = st[p].fail;
    if (!st[p].nxt[c]){
    int np=++sz,q=st[p].fail;
    st[np].len=st[p].len+2;
    while (S[pos-st[q].len-1]!=S[pos]) q=st[q].fail;
    st[np].fail=st[q].nxt[c];
    st[p].nxt[c] = np;
    }
    now=st[p].nxt[c];
    st[now].cnt++;
}
int main()
{
    string ss;  cin>>ss;   int t=ss.size();
    S=ss;
    ss="#"+ss+"#";
    reverse(S.begin(), S.end());
    ss += S;
    n=ss.size(); n--;  for(int i=1;i<=n;i++) s[i]=ss[i];
    m=122;
    get_sa(); get_height();
    LL ans=n*1LL*(n+1)/2-1LL*(t+1)*(t+1); //cout<<ans<<endl;
    for(int i=1;i<=n;i++) ans-=height[i];
    for(int i=0;i<=n;i++)
    {
        x[i]=0; y[i]=0; sa[i]=0; rk[i]=0; height[i]=0;
    }
    n = S.size();
    pam_init();
    for ( int i = 0 ; i < n; i++) extend(S[i]-'a',i);
    ans -= sz-1;
    ans /= 2;
    ans += sz-1;
    printf("%lld\n",ans);
}
View Code

J

思路:分層圖最短路

代碼:

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)
 
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
 
 
template<class T> void _R(T &x) { cin >> x; }
void _R(int &x) { scanf("%d", &x); }
void _R(ll &x) { scanf("%lld", &x); }
void _R(double &x) { scanf("%lf", &x); }
void _R(char &x) { scanf(" %c", &x); }
void _R(char *x) { scanf("%s", x); }
void R() {}
template<class T, class... U> void R(T &head, U &... tail) { _R(head); R(tail...); }
 
 
template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}
 
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
 
/**********showtime************/
 
            const int maxn = 1e3+9;
            vector<pii> mp[maxn];
            int dis[maxn][maxn];
 
            int n,m,s, t, k;
            void bfs(int s) {
                memset(dis, inf, sizeof(dis));
                dis[s][0] = 0;
                queue<pii>que;
                que.push(pii(s, 0));
                while(!que.empty()){
                    int u = que.front().fi;
                    int tk = que.front().se;
                    que.pop();
                    for(pii p : mp[u]) {
                        int v = p.fi, w = p.se;
                        if(tk < k && dis[v][tk+1] > dis[u][tk]) {
                            dis[v][tk+1] = dis[u][tk];
                            que.push(pii(v, tk+1));
                        }
                        if(dis[v][tk] > dis[u][tk] + w) {
                            dis[v][tk] = dis[u][tk] + w;
                            que.push(pii(v, tk));
                        }
                    }
                }
            }
int main(){
            scanf("%d%d%d%d%d", &n, &m, &s, &t, &k);
            for(int i=1; i<=m; i++) {
                int u,v,w;
                scanf("%d%d%d", &u, &v, &w);
                mp[u].pb(pii(v, w));
                mp[v].pb(pii(u, w));
            }
            bfs(s);
            int ans = inf;
            for(int i=0; i<=k; i++) {
                ans = min(ans, dis[t][i]);
            }
            printf("%d\n", ans);
            return 0;
}
View Code

K

思路:枚舉最後兩個零,看前面有多少個後綴$mod3$等於0。對於$"00"$和$"0"$的狀況,最後統計。

代碼:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1000000;
int dp[maxn][20];
char ss[maxn];
int main(){
   string ss; cin>>ss; ss="#"+ss;
   int l=ss.size();
   long long  ans=0;
   for(int i=1;i<=l;i++){
       int x=ss[i]-'0';
       dp[i][x%3]++;
       for(int j=0;j<=2;j++){
         dp[i][(j*10+x)%3]+=dp[i-1][j];
       }
       if(i+2 <= l){
          if(ss[i+1]=='0'&&ss[i+2]=='0'){
             ans += dp[i][0];
          }
       }
   }
   for (int i = 1; i <= l; ++i) {
        if(ss[i] == '0') ans++;
        if(i-1 >= 1 && ss[i-1] == '0' && ss[i] == '0') ans++;
   }
   cout<<ans<<endl;
}
View Code

2019牛客暑期多校訓練營(第五場)

題號 標題 團隊的狀態
A digits 2  經過
B generator 1  經過
C generator 2  經過
D generator 3 未經過
E independent set 1  經過
F maximum clique 1  經過
G subsequence 1  經過
H subsequence 2  經過
I three points 1  經過
J three points 2 未經過

A

思路:輸出n個n。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
int T, n;
int main() {
    scanf("%d", &T);
    while(T--) {
        scanf("%d", &n);
        for (int i = 1; i <= n; ++i) printf("%d", n);
        printf("\n");
    }
    return 0;
}
View Code

B

思路:十進制快速冪。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
#define ll long long
//#define mp make_pair
#define pb emplace_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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
const int maxn=1e6+10;
//head
 
int MOD;
struct Matrix {
    int a[2][2];
    void init() {
        for (int i = 0; i < 2; i++) {
            for (int j = 0; j < 2; j++)
                a[i][j] = 0;
        }
    }
    void _init() {
        init();
        for (int i = 0; i < 2; i++) a[i][i] = 1;
    }
};
 
Matrix mul(Matrix a, Matrix b) {
    Matrix ans;
    ans.init();
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 2; j++) {
            if(a.a[i][j]) {
                for (int k = 0; k < 2; 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) {
    Matrix ans;
    ans._init();
    a = mul(a, a);
    ans = mul(ans, a);
    a = mul(a, a);
    a = mul(a, a);
    ans = mul(ans, a);
    return ans;
}
char ss[maxn];
int main() {
    int x0,x1,a,b; scanf("%d %d %d %d",&x0,&x1,&a,&b);
    scanf("%s",ss); scanf("%d",&MOD);
    Matrix c;  c.init(); c.a[0][0]=a;  c.a[0][1]=b; c.a[1][0]=1;  c.a[1][1]=0;
    Matrix d;  d.init(); d.a[0][0]=x1; d.a[0][1]=0; d.a[1][0]=x0; d.a[1][1]=0;
    Matrix x[10];
    for (int i = 0; i < 10; ++i) {
        if(i == 0) x[i]._init();
        else x[i] = mul(x[i-1], c);
    }
    c._init();
    int l = strlen(ss);
    for (int i = 0; i < l; ++i) {
        c = q_pow(c);
        c = mul(c, x[ss[i]-'0']);
    }
    c=mul(c,d);
    printf("%d\n",c.a[1][0]%MOD);
    return 0;
}
View Code

C

思路:BSGS。須要預處理。

隊友代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
//#define int long long
#define ll long long
#define LL long long
using namespace std;
int x,a,b;
int p,mod,MOD;
int quick(int x,int n){
    int ans=1;
    while(n){
        if(n&1) ans=1ll* ans*x%mod;
        x=1ll*x*x%mod;  n=n/2;
    } return ans;
}
struct Hash {
    static const int MOD = 1999997;
    static const int N = 1e6;
    int head[MOD + 10], nx[N], top;
    int hs[N], id[N];
    void init() {
        memset(head, -1, sizeof head);
        top = 0;
    }
    void insert(int x, int y) {
        int k = x % MOD;
        hs[top] = x; id[top] = y; nx[top] = head[k]; head[k] = top++;
    }
    int find(int x) {
        int k = x % MOD;
        for (int i = head[k]; i != -1; i = nx[i]) {
            if (hs[i] == x) {
                return id[i];
            }
        }
        return -1;
    }
}hs;
void init(int a,int p){
    int m = pow(p,2.0/3.0)+1, s = 1;  //cout<<m<<endl;
    hs.init();
    for(int i = 0; i < m; ++i){
        hs.insert(s,i);   s= (s*1LL*a)%p;
    }
}
int BSGS(int a, int b, int p){
    int m = pow(p,2.0/3.0)+1, s = b;
    int t = quick(a, m);   int ww=quick(b,mod-2);
    s = 1;
    for(int i = 1; i <= p/m+1; ++i){
        s = (s*1LL*t)%p;   if(hs.find(1ll*s*ww%mod) != -1 ) return i*m-hs.find(1ll*s*ww%mod);
    }
    return -1;
}
int32_t main(){
    int T; scanf("%d",&T);
    while(T--){
            ll n;
        scanf("%lld %d %d %d %d",&n,&x,&a,&b,&p); mod=p; MOD=p;
        int q; scanf("%d",&q); init(a,p);
        while(q--){
            ll y; scanf("%lld",&y);
            if(y==x) { printf("0\n");  continue; }
            if(a==0) {      // x b b b b b
                if(y==b)  printf("1\n");
                else     printf("-1\n");
            }
            else if(a==1){  // x+b x+2*b
                y=((y-x)%mod+mod)%mod;  //cout<<y<<endl;
                y=y*quick(b,mod-2)%mod;
                if(1<=y && y<n ) printf("%lld\n",y);
                else              printf("-1\n");
            }
            else {   //cout<<"---------"<<endl;
                y=( 1ll*(a-1)*y%mod+b)%mod*quick( (1ll*(a-1)*x%mod+b)%mod,mod-2)%mod;
                y=BSGS(a,y,p);
                if(1<=y && y<=n ) printf("%lld\n",y);
                else              printf("-1\n");
            }
        }
    }
 
}
View Code

D

E

思路:狀壓dp。有兩個優化的地方,用char開數組優化空間,從最低位轉移優化時間。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
vector<int> g[26];
int n, m, u, v, st[26];
char dp[(1<<26)+10], mp[(1<<26)+10];
int main() {
    scanf("%d %d", &n, &m);
    for (int i = 0; i < m; ++i) {
        scanf("%d %d", &u, &v);
        st[u] |= 1<<v;
        st[v] |= 1<<u;
    }
    for (int i = 0; i < n; ++i) st[i] |= 1<<i;
    int p = 1;
    for (int i = 0; i < n; ++i) mp[p] = i, p <<= 1;
    dp[0] = 0;
    int up = 1<<n, ans = 0;
    for (int i = 1; i < up; ++i) {
        int x = i&-i;
        dp[i] = max(dp[i], dp[i^x]);
        dp[i] = max(dp[i], (char)(dp[i&(~st[mp[x]])]+1));
        ans += dp[i];
    }
    printf("%d\n", ans);
    return 0;
}
View Code

F

思路:最大團轉換成二分圖最大獨立集。

隊友代碼:

// #pragma GCC optimize(2)
// #pragma GCC optimize(3)
// #pragma GCC optimize(4)
#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;

template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}

/**********showtime************/
            const int maxn = 5e3+9;
            int a[maxn];
            int col[maxn];
            vector<int>L, R;
            vector<int>mp[maxn];
            void dfs(int s, int c) {
                col[s] = c;
                for(int i=0; i<mp[s].size(); i++){
                    int v = mp[s][i];
                    if(col[v] == 0) dfs(v, 3 - c);
                }
            }
            int vis[maxn],match[maxn],pt[maxn];
            bool gkd(int u) {
                if(vis[u]) return false;
                vis[u] = true;
                for(int i = 0; i<mp[u].size(); i++) {
                    int v = mp[u][i];
                    if(match[v] == -1 || gkd(match[v]) ){
                        match[v] = u;
                        pt[u] = v;
                        return true;
                    }
                }
                return false;
            }
            int res[maxn];
            bool findmn(int u) {
                if(u == -1) return false;
                if(res[u]) return true;
                // res[u] = 1;
                if(col[u] == 1){
                     if(findmn(pt[u])) {res[u] = 1;return true;}
                     else return false;

                }
                else {
                    res[u] = 1;
                    for(int i=0; i<mp[u].size(); i++) {
                        int v = mp[u][i];
                        if(match[u] == v) continue;
                        findmn(v);
                    }
                    return true;
                }
            }
int main(){ 
            int n;
            scanf("%d", &n);
            for(int i=1; i<=n; i++) scanf("%d", &a[i]);
            for(int i=1; i<=n; i++) {
                for(int j=i+1; j<=n; j++) {
                    if(__builtin_popcount(a[i] ^ a[j]) == 1) {
                        mp[i].pb(j);
                        mp[j].pb(i);
                    }
                }
            }

            for(int i=1; i<=n; i++) if(col[i] == 0) dfs(i, 1);
            
            int cnt = 0;
            memset(match, -1, sizeof(match));
            for(int i=1; i<=n; i++) {
                memset(vis, 0, sizeof(vis));
                if(col[i] == 1 && gkd(i)) cnt++;  
            }

            printf("%d\n", n-cnt);
            for(int i=1; i<=n; i++) {
                if(col[i] == 2 && match[i] == -1) {findmn(i);}
            }

            vector<int>ans;
            for(int i=1; i<=n; i++) {
                if(col[i] == 1 && res[i] == 0) ans.pb(a[i]);
                if(col[i] == 2 && res[i] == 1) ans.pb(a[i]);
            }
            for(int i=0; i<ans.size(); i++) {
                printf("%d ", ans[i]);
            }
            puts("");
            return 0;
}
View Code

G

思路:dp。

代碼:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=3e3+10;
const int mod=998244353;
int dp[maxn][maxn];
char ss[maxn];
char tt[maxn];
int A[maxn];
int B[maxn];
int quick(int x,int n){
    int ans=1;
    while(n){
        if(n&1) ans=1ll*ans*x%mod;
        x=1ll*x*x%mod;
        n=n/2;
    } return ans;
}
int C(int n,int x){
    if(x>n) return 0;
    return 1ll*A[n]*B[n-x]%mod*B[x]%mod;
}
int main(){
    A[0]=1; B[0]=1;
    for(int i=1;i<maxn;i++) A[i]=1ll*A[i-1]*i%mod;
    for(int i=1;i<maxn;i++) B[i]=quick(A[i],mod-2);
    //cout<<1ll*121321*1354534<<endl;
    int T; scanf("%d",&T);
    while(T--){
        int ans=0;
        int n,m; scanf("%d %d",&n,&m);
        scanf("%s",ss+1);
        scanf("%s",tt+1);
        dp[0][0]=1;
        for(int i=1;i<=n;i++){
            if(ss[i]!='0'){
                for(int j=m;j<=n-i;j++){
                    ans+=C(n-i,j); ans=ans%mod;
                }
            }
            for(int j=0;j<=m-1;j++) dp[i][j]=dp[i-1][j];
            for(int j=0;j<=m-1;j++){
                if(ss[i]==tt[j+1]) { dp[i][j+1]+=dp[i-1][j]; dp[i][j+1]%=mod; }
                else if(ss[i]>tt[j+1]){
                    ans+=1ll*dp[i-1][j]*C(n-i,m-j-1)%mod; ans=ans%mod;
                }
            }
        }
        printf("%d\n",ans);
        for(int i=0;i<=n+1;i++){
            for(int j=0;j<=m+1;j++){
                dp[i][j]=0;
            }
        }
    }
    return 0;
}
View Code

H

思路:拓撲排序。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include <bits/stdc++.h>
 
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)
 
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
 
 
 
template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}
 
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
 
/**********showtime************/
 
            const int maxn = 1e4+9;
            int vis[22], visno[22];
            char str[5];
            char res[maxn];
            int tot = 0;
            vector<int> mp[22];
            vector<int>G[maxn*100];
            int pt[maxn*100];
            int du[maxn*100];
            int id[maxn];
            char ans[maxn];
int main(){
            int n,m;
            scanf("%d%d", &n, &m);
            int cnt = m * (m - 1) / 2;
            int flag = 1;
            memset(vis, -1, sizeof(vis));
            for(int i=1; i<=cnt; i++) {
                scanf("%s", str);
                int len;    scanf("%d", &len);
                if(len == 0) {
                    int dd1 = str[0] - 'a';
                    int dd2 = str[1] - 'a';
                    visno[dd1] = visno[dd2] = 1;
                    continue;///
                }
 
                scanf("%s", res);
 
                int dd1 = str[0] - 'a';
                int dd2 = str[1] - 'a';
                if(vis[dd1] == -1) {
                    int cc = 0;
                    for(int j = 0; j<len; j++) {
                        if(res[j] == str[0]) {
                            id[j] = ++tot;
                            mp[dd1].pb(tot);
                            pt[tot] = dd1;
                            cc++;
                        }
                    }
                    vis[dd1] = cc;
                }
                else {
                    int cc = 0;
                    for(int j=0; j<len; j++) {
                        if(res[j] == str[0]) {
                            if(cc < mp[dd1].size()) id[j] = mp[dd1][cc];
                            cc++;
                        }
                    }
                    if(cc != vis[dd1])flag = 0;
                 }
 
                 if(vis[dd2] == -1) {
                    int cc = 0;
                    for(int j = 0; j<len; j++) {
                        if(res[j] == str[1]) {
                            id[j] = ++tot;
                            mp[dd2].pb(tot);
                            pt[tot] = dd2;
                            cc++;
                        }
                    }
                    vis[dd2] = cc;
                }
                else {
                    int cc = 0;
                    for(int j=0; j<len; j++) {
                        if(res[j] == str[1]) {
                            if(cc < mp[dd2].size()) id[j] = mp[dd2][cc];
                            cc++;
                        }
                    }
                    if(cc != vis[dd2])flag = 0;
                 }
                 for(int j=0; j<len-1; j++) {
                    G[id[j]].pb(id[j+1]);
                    du[id[j+1]]++;
                 }
            }
 
            for(int i=0; i<m; i++) {
                if(vis[i] && visno[i]) flag = 0;
            }
            if(!flag || tot != n) puts("-1");
            else {
//                string ans = "";
                int all = 0;
                queue<int>que;
                for(int i=1; i<=tot; i++) if(du[i] == 0) que.push(i);
                while(!que.empty()) {
                    int u = que.front(); que.pop();
//                    ans += pt[u] +'a';
                    ans[all++] = pt[u] + 'a';
                    for(int i=0; i<G[u].size(); i++) {
                        int v = G[u][i];
                        du[v]--;
                        if(du[v] == 0) {
                            que.push(v);
                        }
                    }
                }
                int ff = 1;
                for(int i=1; i<=tot; i++) if(du[i] > 0) ff = 0;
                if(ff == 0) puts("-1");
                else {
                    ans[all] = '\0';
                    printf("%s\n",ans);
                }
            }
            return 0;
}
View Code

I

思路:暴力枚舉每條邊的順序關係。

隊友代碼:

#include<bits/stdc++.h>
using namespace std;
const double eps=1e-7;
const double pi=acos(-1.0);
inline double sqr(double x){ return x*x;                                  }
inline int dcmp(double x)  { if(fabs(x)<eps) return 0;return (x>0? 1: -1);}
struct Point{
    double x,y;
    Point(){ x=0,y=0; }
    Point(double _x,double _y):x(_x),y(_y){}
    bool operator ==(const Point &b)const{return  ( dcmp(x-b.x)==0&&dcmp(y-b.y)==0);      }
    bool operator !=(const Point &b)const{return !((dcmp(x-b.x)==0&&dcmp(y-b.y)==0));     }
    bool operator <(const Point &b)const {return (dcmp(x-b.x)==0? dcmp(y-b.y)<0 : x<b.x); }
    double operator ^(const Point &b)const{     return x*b.y-y*b.x;}//叉積
    double operator *(const Point &b)const{     return x*b.x+y*b.y;} //點積
    Point operator +(const Point &b)const {     return Point(x+b.x,y+b.y);}
    Point operator -(const Point &b)const {     return Point(x-b.x,y-b.y);}
    Point operator *(double a)            {     return Point(x*a,y*a);    }
    Point operator /(double a)            {     return Point(x/a,y/a);    }
    double len2()                         {     return sqr(x)+sqr(y);     }//長度平方
    double len()                          {      return sqrt(len2());     }//長度
    double polar(){  return atan2(y,x);  }//向量的極角   //返回與x軸正向夾角(-pi~pi]
}X,Y,Z;
double dis(Point A,Point B) { return sqrt( (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));}
struct Circle{
    Point c;
    double r;
    Circle() {c.x=0; c.y=0; r=0; }
    Circle(Point c,double r):c(c),r(r) {}
    Point point(double a){
        return Point (c.x+cos(a)*r,c.y+sin(a)*r);
    }
}A,B;
int h,w,a,b,c;
Point Circle_Cirle(Circle c1, Circle c2){
    double d=dis(c1.c,c2.c);   Point k=c2.c-c1.c;
    double a=k.polar();
    double da=acos( (c1.r*c1.r+d*d-c2.r*c2.r)/(2*c1.r*d) );
    Point p1=c1.point(a-da);  //printf("%.10f %.10f\n",p1.x,p1.y);
    Point p2=c1.point(a+da); // printf("%.10f %.10f\n",p2.x,p2.y);
   // cout<<h<<" "<<w<<endl;
    if(-eps<=p1.x && p1.x<=h+eps && p1.y<=w+eps && p1.y>=-eps) return p1;
    if(-eps<=p2.x && p2.x<=h+eps && p2.y<=w+eps && p2.y>=-eps) return p2;
    Point p={-1,-1};
    return p;
}
void make(Point &XX,int aa,Point &YY,int bb,Point &ZZ,int cc){
    XX.x=0; XX.y=0;
    if(aa<=h) { YY.x=aa;  YY.y=0; }
    else      { double qq=sqrt(1.0*aa*aa-1.0*h*h);  YY.x=h; YY.y=qq;  }
    A.c=XX; A.r=cc;
    B.c=YY; B.r=bb;
    ZZ=Circle_Cirle(A,B);
   // cout<<A.c.x<<"  "<<A.c.y<<" "<<A.r<<endl;
   // cout<<B.c.x<<"  "<<B.c.y<<"  "<<B.r<<endl;
  //  printf("%.10f %.10f %.10f %.10f %.10f %.10f\n",abs(X.x),abs(X.y),abs(Y.x),abs(Y.y),abs(Z.x),abs(Z.y));
}
bool check(){
    if( abs(dis(X,Y)-a)<eps && abs(dis(X,Z)-b)<eps && abs(dis(Y,Z)-c)<eps
        && X.x>=-eps  && X.x<=h+eps
        && X.y>=-eps  && X.y<=w+eps
        && Y.x>=-eps  && Y.x<=h+eps
        && Y.y>=-eps  && Y.y<=w+eps
        && Z.x>=-eps  && Z.x<=h+eps
        && Z.y>=-eps  && Z.y<=w+eps
       ) return 1;
        return 0;
}
void work(){
    X.x=0; X.y=0; Y.x=0; Y.y=0; Z.x=0; Z.y=0; make(X,a,Y,c,Z,b);  if(check()) return ;
    X.x=0; X.y=0; Y.x=0; Y.y=0; Z.x=0; Z.y=0; make(X,b,Z,c,Y,a);  if(check()) return ;
    X.x=0; X.y=0; Y.x=0; Y.y=0; Z.x=0; Z.y=0; make(Y,a,X,b,Z,c);  if(check()) return ;
    X.x=0; X.y=0; Y.x=0; Y.y=0; Z.x=0; Z.y=0; make(Y,c,Z,b,X,a);  if(check()) return ;
    X.x=0; X.y=0; Y.x=0; Y.y=0; Z.x=0; Z.y=0; make(Z,b,X,a,Y,c);  if(check()) return ;
    X.x=0; X.y=0; Y.x=0; Y.y=0; Z.x=0; Z.y=0; make(Z,c,Y,a,X,b);  if(check()) return ;
}
int main(){
    int T; scanf("%d",&T);
    while(T--){
        scanf("%d %d %d %d %d",&h,&w,&a,&b,&c);
        int flag=0; if(h<w) { swap(h,w); flag=1; }
        work();
        if(flag==1){ swap(X.x,X.y); swap(Y.x,Y.y); swap(Z.x,Z.y); }
        //printf("%.10f\n",dis(X,Y));
        //printf("%.10f\n",dis(X,Z));
        //printf("%.10f\n",dis(Y,Z));
        printf("%.10f %.10f %.10f %.10f %.10f %.10f\n",abs(X.x),abs(X.y),abs(Y.x),abs(Y.y),abs(Z.x),abs(Z.y));
    }
}
View Code

J

2019牛客暑期多校訓練營(第六場)

題號 標題 團隊的狀態
A Garbage Classification  經過
B Shorten IPv6 Address  經過
C Palindrome Mouse  經過
D Move  經過
E Androgynos  經過
F K-ary Heap 未經過
G Is Today Friday?  經過
H Train Driver  經過
I Can They Go to Galar? 未經過
J Upgrading Technology  經過

A

思路:暴力。

代碼:

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e3+10;
char ss[maxn];
char tt[maxn];
map<char,char> mp;
int main(){
    int T; scanf("%d",&T); int tot=0;
    while(T--){
        scanf("%s",ss); int l=strlen(ss);
        scanf("%s",tt); int r=strlen(tt);
        char x='a';
        for(int i=0;i<r;i++) {
            mp[x]=tt[i]; x++;
        }
        int a=0;
        int b=0;
        int c=0;
        for(int i=0;i<l;i++){
            if(mp[ss[i]]=='h') a++;
            if(mp[ss[i]]=='d') b++;
            if(mp[ss[i]]=='w') c++;
        }
        if(4*a>=l){
            printf("Case #%d: Harmful\n",++tot);
        }
        else if(10*a<=l){
             printf("Case #%d: Recyclable\n",++tot);
        }
        else if(b>=2*c){
            printf("Case #%d: Dry\n",++tot);
        }
        else {
            printf("Case #%d: Wet\n",++tot);
        }
        mp.clear();
    }
}
View Code

B

思路:注意若是連續的0在最前面或最後面會少一個冒號。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
int T;
string s;
set<string> st;
string x[15];
int l[10];
int main() {
    fio;
    cin >> T;
    for(int cs = 1; cs <= T; ++cs) {
        cin >> s;
        int now = 0;
        for (int i = 0; i < 128; i += 16) {
            string res = "";
            int v = 0;
            for (int j = i; j < i+16; j ++) {
                if(j != i && (j-i)%4 == 0) {
                    if(v == 0) {
                        if(res.size() == 0);
                        else res += '0';
                    }
                    else {
                        if(v >= 10) res += char(v-10+'a');
                        else res += char(v+'0');
                    }
                    v = 0;
                }
                v = v*2+s[j]-'0';
            }
            if(v == 0) {
                if(res.size() == 0);
                else res += '0';
            }
            else {
                if(v >= 10) res += char(v-10+'a');
                else res += char(v+'0');
            }
            if(res.size() == 0) res = "0";
            x[++now] = res;
        }
        int mx = 0;
        for (int i = 1; i <= now; ++i) {
            if(x[i] == "0") l[i] = l[i-1]+1;
            else l[i] = 0;
            mx = max(mx, l[i]);
        }
        if(mx <= 1){
            string t = "";
            for (int i = 1; i <= now; ++i) {
                t += x[i];
                if(i != now) t += ":";
            }
            st.insert(t);
        }
        else {
            for (int i = 1; i <= now; ++i) {
                if(l[i] == mx && i-mx != 0 && i != now) {
                    string t = "";
                    for (int j = 1; j <= i-mx; ++j) {
                        t += x[j];
                        if(j != i-mx) t += ":";
                    }
                    t += "::";
                    for (int j = i+1; j <= now; ++j) {
                        t += x[j];
                        if(j != now) t += ":";
                    }
                    st.insert(t);
                }
            }
            if(st.empty()) {
                for (int i = 1; i <= now; ++i) {
                    if(l[i] == mx) {
                        string t = "";
                        for (int j = 1; j <= i-mx; ++j) {
                            t += x[j];
                            if(j != i-mx) t += ":";
                        }
                        t += "::";
                        for (int j = i+1; j <= now; ++j) {
                            t += x[j];
                            if(j != now) t += ":";
                        }
                        st.insert(t);
                    }
                }
            }
        }
 
        cout << "Case #" << cs << ": "<< *(st.begin()) << "\n";
 
        for (int i = 1; i <= now; ++i) l[i] = 0;
        string().swap(s);
        st.clear();
    }
    return 0;
}
View Code

C

思路:迴文自動機上亂跳。

隊友代碼:

#include<bits/stdc++.h>
#define ll long long
#define LL long long
using namespace std;
const int maxn=1e5+10;
char ss[maxn];
struct PAM{
    #define ll long long
    #define LL long long
    static const int maxn=3e5+10;
    static const int num=27;
    int fail[maxn],cnt[maxn],len[maxn],ch[maxn][num],vis[maxn];
    int last,tot;
    LL ans;
    void inint(){
        last=0;  tot=0;
        fail[0]=fail[1]=1;
        len[0]=0; len[1]=-1; tot++; ans=0;
    }
    int get_fail(int p,int pos){
         while(ss[pos-len[p]-1]!=ss[pos]) p=fail[p];
         return p;
    }
    void add(int x,int pos){
        int p=get_fail(last,pos);
        if(!ch[p][x]){
            len[++tot]=len[p]+2;
            fail[tot]=ch[get_fail(fail[p],pos)][x];
            ch[p][x]=tot;
        }
        cnt[last=ch[p][x]]++;
    }
    void count(){  //  bu zhi bu tong hui wen ge shu
        for(int i=tot;i>=0;i--){
            cnt[fail[i]]+=cnt[i];
        }
    }
 
    void clear(){
        for(int i=0;i<=tot;i++){
            fail[i]=0; len[i]=0; cnt[i]=0; vis[i]=0;
            for(int j=0;j<num;j++) ch[i][j]=0;
        }
        last=tot=ans=0;
    }
    void dfs(int u,int s){
        vector<int> vs; //cout<<"---"<<s<<endl;
        for(int i=fail[u];i>=1;i=fail[i]){
            if(vis[i]==1) break;
            s++; vis[i]=1;
            vs.push_back(i);
        }
        ans+=s;// cout<<s<<endl;
        if(vis[u]==0) { vis[u]=1; s++; }
        for(int i=0;i<26;i++){
            if(ch[u][i]){
                dfs(ch[u][i],s);
            }
        }
        if(u!=0 && u!=1) vis[u]=0;
        for(int i=0;i<vs.size();i++) vis[vs[i]]=0;
    }
    void work(){
        vis[0]=1;  vis[1]=1;  //cout<<ans<<endl;
        dfs(0,0);
        dfs(1,0);
    }
}pam;
int main(){
    int T; scanf("%d",&T);  int tot=0;
    while(T--){
        scanf("%s",ss);  int l=strlen(ss);
        pam.inint();
        for(int i=0;i<l;i++) pam.add(ss[i]-'a',i);
        pam.work();
        printf("Case #%d: %lld\n",++tot,pam.ans);
        pam.clear();
    }
 
}
View Code

D

思路:算一個下界,暴力計算。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
const int N = 1e3 + 5;
vector<int> vc;
int v[N], T, n, k;
multiset<int> a, b;
int main() {
    scanf("%d", &T);
    for (int cs = 1; cs <= T; ++cs) {
        scanf("%d %d", &n, &k);
        for (int i = 1; i <= n; ++i) scanf("%d", &v[i]), a.insert(v[i]);
        int sum = 0, mx = 0;
        for (int i = 1; i <= n; ++i) sum += v[i], mx = max(mx, v[i]);
        int dw = max(mx, (sum+k-1)/k);
        for (int i = dw; ; ++i) {
            int tt = 0, now = 0, up = i;
            b = a;
            while(!b.empty()) {
                auto t = b.upper_bound(up-now);
                if(t == b.begin()) {
                    now = 0;
                    ++tt;
                }
                else {
                    --t;
                    now += *t;
                    b.erase(b.find(*t));
                }
            }
            if(now) ++tt;
            if(tt <= k) {
                printf("Case #%d: %d\n", cs, up);
                break;
            }
        }
 
        a.clear();
        b.clear();
    }
    return 0;
}
View Code

E

思路:4個一塊兒構造,最後若是剩下5個單獨構造。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include <bits/stdc++.h>
 
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)
 
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
 
 
 
template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}
 
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
 
/**********showtime************/
 
            const int maxn = 2009;
            int mp[maxn][maxn];
            int pt[maxn];
 
            void solve(int le, int ri) {
                if(ri - le + 1 == 5) {
                    for(int i=le; i<ri; i++) {
                        mp[i+1][i] = mp[i][i+1] = 1;
                        pt[i] = i+1;
                    }
                    mp[le][ri] = mp[ri][le] = 1;
                    pt[le] = le;
                    pt[le+1] = le+2;
                    pt[ri] = ri-1;
                    pt[le+2] = ri;
                    pt[le+3] = le+1;
                }
                else if(ri - le + 1 == 4) {
                    mp[le][le+2] = mp[le+2][le] = 1;
                    mp[le][le+1] = mp[le+1][le] = 1;
                    mp[le+1][le+3] = mp[le+3][le+1] = 1;
                    pt[le] = le + 2;
                    pt[le+1] = le + 3;
                    pt[le+2] = le+1;
                    pt[le+3] = le;
                }
                else {
                    mp[le][le+2] = mp[le+2][le] = 1;
                    mp[le][le+1] = mp[le+1][le] = 1;
                    mp[le+1][le+3] = mp[le+3][le+1] = 1;
                    pt[le] = le + 2;
                    pt[le+1] = le + 3;
                    pt[le+2] = le+1;
                    pt[le+3] = le;
                    for(int i= le+4; i<=ri; i++) {
                        mp[le+2][i] = 1;
                        mp[i][le+2] = 1;
 
                        mp[le+3][i] = 1;
                        mp[i][le+3] = 1;
                    }
                    solve(le+4, ri);
                }
            }
int main(){
            int T;  scanf("%d", &T);
            int cas = 0;
            while(T--) {
                int n;  scanf("%d", &n);
                if(n == 1) {
                    printf("Case #%d: Yes\n", ++cas);
                    printf("0\n1\n");
                }
                else if(n < 4)
                    printf("Case #%d: No\n", ++cas);
                else {
                    if(n * (n-1) % 4)
                            printf("Case #%d: No\n", ++cas);
                    else {
                        printf("Case #%d: Yes\n", ++cas);
                        for(int i=1; i<=n; i++) {
                            for(int j=1; j<=n; j++) mp[i][j] = 0;
                            pt[i] = 0;
                        }
                        solve(1, n);
                        for(int i=1; i<=n; i++) {
                            for(int j=1; j<=n; j++) {
                                printf("%d",mp[i][j]);
                            }
                            puts("");
                        }
                        for(int i=1; i<n; i++) printf("%d ", pt[i]);
                        printf("%d\n", pt[n]);
                    }
                }
            }
            return 0;
}
View Code

F

G

思路:暴力枚舉排列,而後判斷每個是否能夠(用蔡勒公式),因爲存在的狀況不多,因此判斷只要不多就能退出。除了一種狀況,一直都是能夠的,

可是本質不一樣的能夠的不多,因此這種狀況確定有不少重複的。因此暴力前先去個重。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
int T, n;
vector<string> s;
int a[10];
int month[2][12] = {
    {31,28,31,30,31,30,31,31,30,31,30,31},
    {31,29,31,30,31,30,31,31,30,31,30,31}
};
inline bool ck(int x) {
    return (x%4==0&&x%100!=0) || x%400==0;
}
inline int caile(int x, int y, int z) {
    if(x < 1600) return 0;
    if(y > 12 || y == 0) return 0;
    if(ck(x)) {
        if(z == 0 || z > month[1][y-1]) return 0;
    }
    else {
        if(z == 0 || z > month[0][y-1]) return 0;
    }
    if(y <= 2) y += 12, x--;
    return ((x/100/4-2*(x/100)+x%100+x%100/4+26*(y+1)/10+z-1)%7+7)%7;
}
int main() {
    fio;
    cin >> T;
    for (int cs = 1; cs <= T; ++cs) {
        cin >> n;
        s.resize(n);
        for (int i = 0; i < n; ++i) cin >> s[i];
        sort(s.begin(), s.end());
        s.erase(unique(s.begin(), s.end()), s.end());
        for (int i = 0; i < 10; ++i) a[i] = i;
        bool ok = false;
        do {
            bool f = true;
            for (int i = 0; i < s.size(); ++i) {
                int x = 0, y = 0, z = 0;
                for (int j = 0; j < 4; ++j) x = x*10 + a[s[i][j]-'A'];
                for (int j = 5; j < 7; ++j) y = y*10 + a[s[i][j]-'A'];
                for (int j = 8; j < 10; ++j) z = z*10 + a[s[i][j]-'A'];
                if(caile(x, y, z) == 5) ;
                else {
                    f = false;
                    break;
                }
            }
            if(f)  {
                ok = true;
                cout << "Case #" << cs << ": ";
                for (int i = 0; i < 10; ++i) cout << a[i];
                cout << "\n";
                break;
            }
            else continue;
        }while(next_permutation(a, a+10));
        if(!ok)  cout << "Case #" << cs << ": Impossible\n";
    }
    return 0;
}
View Code

H

思路:先用bfs預處理每一個$a$集合和$b$集合的點到其餘點的最短距離。而後枚舉$a$集合的點$x$和$b$集合的點$y$,把每一個點到$x$的距離和到$y$的距離加起來做爲初始值,

而後來更新其餘點的最短距離,因爲不能有$logn$的複雜度,因此要先對距離哈希排序,而後用兩個隊列來更新,每次取兩個隊列隊首最小值更新。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
const int N = 1e5 + 5;
int T, n, m, u, v;
vector<int> g[N], vc[N*2];
int a[22], b[22], da[22][N], db[22][N], ca, cb;
int q[N*2], l1, r1, l2, r2, dis[N];
pii q1[N*2], q2[N*2];
inline void bfs(int u, int *dis) {
    for (int i = 1; i <= n; ++i) dis[i] = -1;
    dis[u] = 0;
    int l = 1, r = 0;
    q[++r] = u;
    while(l <= r) {
        int u = q[l++];
        for (int v : g[u]) {
            if(~dis[v]) ;
            else dis[v] = dis[u]+1, q[++r] = v;
        }
    }
}
inline LL solve(int x, int y) {
    LL ans = 0;
    for (int i = 1; i <= n; ++i) vc[da[x][i]+db[y][i]].pb(i), dis[i] = -1;
    int l1 = 1, r1 = 0, l2 = 1, r2 = 0;
    for (int i = 0; i <= 2*n; ++i) {for (int u : vc[i]) q1[++r1] = {i, u}; vc[i].clear();}
    while(l1 <= r1 || l2 <= r2) {
        if(l1 <= r1 && l2 <= r2) {
            if(q1[l1].fi < q2[l2].fi) {
                int d = q1[l1].fi, u = q1[l1].se;
                ++l1;
                if(~dis[u]) continue;
                dis[u] = d;
                for (int v : g[u]) if(dis[v] == -1) q2[++r2] = {d+1, v};
            }
            else {
                int d = q2[l2].fi, u = q2[l2].se;
                ++l2;
                if(~dis[u]) continue;
                dis[u] = d;
                for (int v : g[u]) if(dis[v] == -1) q2[++r2] = {d+1, v};
            }
        }
        else if(l1 <= r1) {
            int d = q1[l1].fi, u = q1[l1].se;
            ++l1;
            if(~dis[u]) continue;
            dis[u] = d;
            for (int v : g[u]) if(dis[v] == -1) q2[++r2] = {d+1, v};
        }
        else {
            int d = q2[l2].fi, u = q2[l2].se;
            ++l2;
            if(~dis[u]) continue;
            dis[u] = d;
            for (int v : g[u]) if(dis[v] == -1) q2[++r2] = {d+1, v};
        }
    }
    for (int i = 1; i <= n; ++i) ans += dis[i];
    return ans;
}
int main() {
    scanf("%d", &T);
    for (int cs = 1; cs <= T; ++cs) {
        scanf("%d %d", &n, &m);
        for (int i = 1; i <= m; ++i) scanf("%d %d", &u, &v), g[u].pb(v), g[v].pb(u);
        scanf("%d", &ca); for (int i = 1; i <= ca; ++i) scanf("%d", &a[i]);
        scanf("%d", &cb); for (int i = 1; i <= cb; ++i) scanf("%d", &b[i]);
        for (int i = 1; i <= ca; ++i) bfs(a[i], da[i]);
        for (int i = 1; i <= cb; ++i) bfs(b[i], db[i]);
        LL ans = 0;
        for (int i = 1; i <= ca; ++i) {
            for (int j = 1; j <= cb; ++j) {
                LL t = solve(i, j);
                ans += t;
            }
        }
        LL d = ca*1LL*cb*1LL*n;
        LL dd = __gcd(d, ans);
        d /= dd, ans /= dd;
        printf("Case #%d: %lld/%lld\n", cs, ans, d);
        for (int i = 1; i <= n; ++i) g[i].clear();
    }
    return 0;
}
View Code

I

J

思路:注意若是要最多達到$level_i$,至少有一個技能正好是$lelel_i$。

代碼:

/*
* @Author: chenkexing
* @Date:   2019-08-02 20:30:39
* @Last Modified by:   chenkexing
* @Last Modified time: 2019-08-02 22:33:17
*/
// #pragma GCC optimize(2)
// #pragma GCC optimize(3)
// #pragma GCC optimize(4)
#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)
 
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
 
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
 
template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}
 
/**********showtime************/
            const int maxn = 1009;
            ll a[maxn][maxn];
            ll sum[maxn][maxn];
            ll ss[maxn][maxn];
            ll b[maxn];
int main(){
            int T;  scanf("%d", &T);
            int cas = 0;
            while(T--) {
                int n,m;
                scanf("%d%d", &n, &m);
                for(int i=1; i<=n; i++) {
                    for(int j=1; j<=m; j++) {
                        scanf("%lld", &a[i][j]);
                    }
                }
                for(int i=0; i<=n; i++) {
                    for(int j=0; j<=m; j++) {
                        sum[i][j] = ss[i][j] = 0;
                    }
                }
                for(int i=1; i<=m; i++) scanf("%lld", &b[i]);
                for(int i=1; i<=n; i++) {
                    for(int j=1; j<=m; j++) sum[i][j] = sum[i][j-1] + a[i][j], ss[i][j] = sum[i][j];
                    for(int j=m-1; j>=0; j--) sum[i][j] = min(sum[i][j], sum[i][j+1]);
                }
                ll ans = 0, allb = 0;
                for(int i=0; i<=m; i++) {
                    ll tmp = 0;
                    allb += b[i];
                    for(int j=1; j<=n; j++) {
                        tmp += sum[j][i];
                    }
                    for(int j=1; j<=n; j++) {
                        tmp -= sum[j][i];
                        tmp += ss[j][i];
                        ans = max(ans, allb - tmp);
                        tmp += sum[j][i];
                        tmp -= ss[j][i];
                    }
                }
                printf("Case #%d: %lld\n",++cas,  ans);
            }
            return 0;
}
View Code 

2019牛客暑期多校訓練營(第七場)

題號 標題 團隊的狀態
A String  經過
B Irreducible Polynomial  經過
C Governing sand  經過
D Number  經過
E Find the median  經過
F Energy stones 未經過
G Make Shan Happy 未經過
H Pair  經過
I Chessboard 未經過
J A+B problem  經過
K Function 未經過

A

思路:$O(n^3)$的dp加最小表示法。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
string s;
int Min(string s) {
    int i = 0, j = 1, k = 0, n = s.size(), d;
    while(i < n && j < n && k < n) {
        d = s[(i+k)%n] - s[(j+k)%n];
        if(!d) k++;
        else {
            if(d > 0) i += k+1;
            else j += k+1;
            if(i == j) j++;
            k = 0;
        }
    }
    return min(i, j);
}
const int N = 222;
int T, dp[N], pre[N], can[N][N];
int main() {
    fio;
    cin >> T;
    while(T--) {
        cin >> s;
        int n = s.size();
        for (int i = 0; i <= n; ++i) dp[i] = 2*n;
        for (int i = 1; i <= n; ++i) {
            string t = "";
            for (int j = i; j <= n; ++j) {
                t += s[j-1];
                if(Min(t) == 0) can[i][j] = 1;
                else can[i][j] = 0;
            }
        }
        dp[0] = 1;
        for (int i = 1; i <= n; ++i) {
            for (int j = 0; j < i; ++j) {
                if(dp[j] && can[j+1][i] && dp[j]+1 <= dp[i]) {
                    dp[i] = dp[j]+1;
                    pre[i] = j;
                }
            }
        }
        vector<int> vc;
        int now = n;
        vc.pb(n);
        while(pre[now]) {
            now = pre[now];
            vc.pb(now);
        }
        vc.pb(0);
        reverse(vc.begin(), vc.end());
        for (int i = 1; i < vc.size(); ++i) {
            for (int j = vc[i-1]; j < vc[i]; ++j) cout << s[j];
            if(i+1 != vc.size())cout << " ";
        }
        cout << endl;
    }
    return 0;
}
View Code

B

思路:由於三次及以上實係數多項式至少有一個實零點,因此它能夠分解。

代碼:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=13;
int a[maxn];
int main(){
    int T; scanf("%d",&T);
    while(T--){
        int n; scanf("%d",&n);
        for(int i=n;i>=0;i--){
            scanf("%d",&a[i]);
        }
        if(n>2) printf("No\n");
        else if(n<2) printf("Yes\n");
        else {
            long long c=a[1]*a[1]-4*a[2]*a[0];
            if(c<0) printf("Yes\n");
            else printf("No\n");
        }
    }
}
View Code

C

思路:暴力

代碼:

// #pragma GCC optimize(2)
// #pragma GCC optimize(3)
// #pragma GCC optimize(4)
#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)
 
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
 
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;
 
template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}
 
/**********showtime************/
 
            const int maxn = 1e5+9;
            struct E{
                ll h,c,p;
            }a[maxn];
            bool cmp(E a, E b) {
                return a.h < b.h;
            }
            ll sum[maxn];
            ll jilu[209];
int main(){
            int n;
            while(~scanf("%d", &n)) {
                ll ans = inff;
                for(int i=1; i<=n; i++) {
                    scanf("%lld%lld%lld", &a[i].h, &a[i].c, &a[i].p);
                }
                sort(a+1, a+1+n, cmp);
                sum[n+1] = 0;
                for(int i=n; i>=1; i--) {
                    sum[i] = sum[i+1] + 1ll*a[i].c * a[i].p;
                }
                for(int i=0; i<209; i++) jilu[i] = 0;
                a[n+1].h = inf;
                int las = 1;
                ll cnt = 0;
                for(int i=1; i<=n; i++) {
                    if(a[i].h < a[i+1].h) {
                        cnt += a[i].p;
                        ll tmp = sum[i+1];
                        ll baoliu = 0;
                        ll cc = cnt - 1;
                        for(int j=202; j>=0 && cc; j--) {
                            ll yong = min(jilu[j], cc);
                            baoliu += yong * j;
                            cc -= yong;
                        }
                        tmp = tmp + sum[1] - sum[las] - baoliu;
//                        debug(tmp);
                        ans = min(ans, tmp);
 
                        for(int j=las; j<=i; j++)
                            jilu[a[j].c] += a[i].p;
                        las = i+1;
                        cnt = 0;
                    }
                    else {
                        cnt += a[i].p;
                    }
                }
                printf("%lld\n", ans);
            }
            return 0;
}
View Code

D

思路:看位數夠不夠,夠的話輸出一個,後面補0,不然就是不能夠。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
LL n, p;
int main() {
    scanf("%lld %lld", &n, &p);
    LL t = p;
    int cnt = 0;
    while(t) t /= 10, ++cnt;
    if(n >= cnt) {
        for (int i = 0; i < n/cnt; ++i) printf("%lld", p);
        for (int i = 0; i < n%cnt; ++i) printf("0");
        printf("\n");
    }
    else printf("T_T\n");
    return 0;
}
View Code

E

思路:離散化+線段樹

代碼:

#pragma GCC optimize(2)
 #pragma GCC optimize(3)
 #pragma GCC optimize(4)
#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)
  
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
  
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;
  
template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}
  
/**********showtime************/
            const int big = 1e9;
            const int maxn = 400005;
            int X[maxn],Y[maxn];
            int L[maxn], R[maxn];
            int a1,b1,c1,m1;
            int a2,b2,c2,m2;
            struct node{
                int cnt;
                ll sum;
                int lazy;
                int len;
            } tree[maxn * 8];
            vector<int>vec;
            int getid(int x) {
                return lower_bound(vec.begin(), vec.end(), x) - vec.begin() + 1;
            }
 
 
            void pushdown(int le,int ri,int rt) {
                tree[rt<<1].cnt += tree[rt].lazy;
                tree[rt<<1|1].cnt += tree[rt].lazy;
                tree[rt<<1].lazy += tree[rt].lazy;
                tree[rt<<1|1].lazy += tree[rt].lazy;
                int mid = (le + ri) >> 1;
 
                tree[rt<<1].sum +=  1ll*tree[rt].lazy * (vec[mid] - vec[le-1]);
                tree[rt<<1|1].sum +=  1ll*tree[rt].lazy *(vec[ri] - vec[mid]);
                tree[rt].lazy = 0;
            }
 
             
            void update(int L, int R, int le, int ri, int rt) {
                if(le >= L && ri <= R) {
                    tree[rt].lazy++;
                    tree[rt].cnt++;
                    tree[rt].sum += 1ll*(vec[ri] - vec[le - 1]);
                    return;
                }
                int mid = (le + ri) >> 1;
                if(tree[rt].lazy) pushdown(le,ri,rt);
                if(mid >= L) {
                    update(L, R, le, mid, rt<<1);
                }
                if(mid < R) {
                    update(L, R, mid+1, ri, rt<<1|1);
                }
                tree[rt].sum = tree[rt<<1].sum + tree[rt<<1|1].sum;
            }
 
            int query(ll tot, int le, int ri, int rt) {
                if(le == ri) {
 
                    int cnt = tree[rt].cnt, res;
                    int lbound = vec[le-1];
                    if(tot % cnt == 0) {
                        res = lbound + tot / cnt - 1;
                    }
                    else
                        res = lbound + tot / cnt;
                    return res;
 
                }
  
                int mid = (le + ri) >> 1;
                if(tree[rt].lazy) pushdown(le,ri,rt);
  
                ll lsum = tree[rt<<1].sum;
                if(lsum >= tot) return query(tot,le, mid, rt<<1);
                else return query(tot - lsum, mid+1, ri, rt<<1|1);
            }
int main(){
  
            int n;
            scanf("%d", &n);
            scanf("%d%d%d%d%d%d", &X[1], &X[2], &a1, &b1, &c1, &m1);
            scanf("%d%d%d%d%d%d", &Y[1], &Y[2], &a2, &b2, &c2, &m2);
             
            L[1] = min(X[1], Y[1]) + 1;
            R[1] = max(X[1], Y[1]) + 1;
            L[2] = min(X[2], Y[2]) + 1;
            R[2] = max(X[2], Y[2]) + 1;
            R[1] ++; R[2] ++;
            vec.pb(L[1]);vec.pb(R[1] );
            vec.pb(L[2]);vec.pb(R[2]);
            for(int i=3; i<=n; i++) {
                X[i] = (1ll*a1 * X[i-1] + 1ll*b1 * X[i-2] + c1 )% m1;
                Y[i] = (1ll*a2 * Y[i-1] + 1ll*b2 * Y[i-2] + c2 )% m2;
                L[i] = min(X[i], Y[i]) + 1;
                R[i] = max(X[i], Y[i]) + 1;
                R[i] ++;
                vec.pb(L[i]);   vec.pb(R[i]);
            }
            sort(vec.begin(), vec.end());
            vec.erase(unique(vec.begin(), vec.end()), vec.end());
            for(int i=1; i<=n; i++) {
                L[i] = getid(L[i]);
                R[i] = getid(R[i]);
            }
             
            int tot = vec.size();
 
            ll all = 0;
 
            for(int i=1; i<=n; i++) {
                 
                update(L[i], R[i] - 1, 1, tot, 1);
 
                all += 1ll*(vec[R[i]-1] - vec[L[i] - 1]);
                 
                printf("%d\n", query((all + 1)/2, 1, tot, 1));
            }
            return 0;
}
View Code

F

G

H

思路:數位dp

代碼:

/*
* @Author: chenkexing
* @Date:   2019-08-09 23:58:00
* @Last Modified by:   chenkexing
* @Last Modified time: 2019-08-10 22:19:16
* @Link https://ac.nowcoder.com/acm/contest/887/H
*/
// #pragma GCC optimize(2)
//  #pragma GCC optimize(3)
//  #pragma GCC optimize(4)
#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)
   
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
   
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;
   
template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}
   
/**********showtime************/
            ll dp[35][2][2][2][2][3][3];
            //dp[len][limit1][limit2][ok1][ok2]
            //因爲兩個數要大於0,因此多加上ok1,ok2.
            //f1 &的, f2 ^的
            int shuA[35],shuB[35],shuC[35];
            ll dfs(int len, int limit1, int limit2, int ok1, int ok2, int f1, int f2){
                if(f1 == 2 && f2 == 2) return 0;
                if(dp[len][limit1][limit2][ok1][ok2][f1][f2] != -1)
                    return dp[len][limit1][limit2][ok1][ok2][f1][f2];
                if(len == 0) {
                    return ok1 && ok2 && (f1 == 1 || f2 == 1);
                } 
  
                int up1 = 1, up2 = 1;
                if(limit1) up1 = shuA[len];
                if(limit2) up2 = shuB[len];
                ll res = 0;
                // cout<<len<<" " << up1<<" , " << up2<<endl;
                for(int i=0; i<=up1; i++) {
                    for(int j=0; j<=up2; j++) {
                          
                        // if(len == 2)cout<<len << " " << i << " , " << j << "  = " << f1 <<" , , " <<f2 << endl;
  
                        if(f1 == 1 || f2 == 1) res += dfs(len-1, limit1 && i == up1, limit2 && j == up2, ok1 || i, ok2 || j, f1, f2);
                        else {
                            int F1 = f1, F2 = f2;
                            if((i & j) < shuC[len]) F1 = 2;
                            else if((i & j) > shuC[len]) F1 = max(F1, 1);
  
                            if((i ^ j) > shuC[len]) F2 = 2;
                            else if((i ^ j) < shuC[len]) F2 = max(F2, 1);
                            res += dfs(len-1, limit1 && i == up1, limit2 && j == up2, ok1 || i, ok2 || j, F1, F2);
                        } 
                    }
  
                }
                dp[len][limit1][limit2][ok1][ok2][f1][f2] = res;
                return res;
            }
  
int main(){
            int T;  scanf("%d", &T);
            while(T--) {
                int a, b, c;
                scanf("%d%d%d", &a, &b, &c);
                memset(dp, -1, sizeof(dp));
                int len = 32;
                for(int i=1; i<=len; i++) shuA[i] = a % 2, a = a >> 1;
                 for(int i=1; i<=len; i++) shuB[i] = b % 2, b = b >> 1;
                for(int i=1; i<=len; i++) shuC[i] = c % 2, c = c >> 1;
                printf("%lld\n", dfs(len, 1, 1, 0, 0, 0, 0));
            }
            return 0;
}
View Code

I

J
思路:水題

代碼:

// #pragma GCC optimize(2)
// #pragma GCC optimize(3)
// #pragma GCC optimize(4)
#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)
 
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
 
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;
 
template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}
 
/**********showtime************/
 
            const int maxn = 50009;
            int p[maxn], a[maxn];
            int ans[maxn];
            int shu[maxn];
            ll f(ll val) {
                int len = 0;
                while(val > 0 && val % 10 == 0) val /= 10;
                while(val > 0) {
                    shu[++len] = val % 10;
                    val = val / 10;
                }
                ll res = 0;
                for(int i=1; i<=len; i++) {
                    res = res * 10 + shu[i];
                }
                return res;
            }
int main(){
            int T;  scanf("%d", &T);
            while(T--) {
                ll a, b;
                scanf("%lld%lld", &a, &b);
                printf("%lld\n", f(f(a) + f(b)));
            }
            return 0;
}
View Code

K

2019牛客暑期多校訓練營(第八場)

題號 標題 團隊的狀態
A All-one Matrices  經過
B Beauty Values  經過
C CDMA  經過
D Distance  經過
E Explorer  經過
F Flower Dance  經過
G Gemstones  經過
H How Many Schemes 未經過
I Inner World  經過
J Just Jump  經過

A

思路:一個左上角的點和右邊界三個值能夠肯定一個矩陣,而後unorded_map去重被卡,最後用手寫bitmap過了(由於bool是一個字節的開不下,bitset也開不下)。正解是單調棧。

bitmap代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
  
const int N = 3e3 + 5;
const int MOD = 2e9 + 7;
short l[N][N], r[N][N], up[N][N];
int n, m;
class BitMap {
public:
    BitMap(int num):n(num),mask(0x1F),shift(5),pos(1<<mask),a(1+n/32,0){}
    void set(int i) {
        a[i>>shift] |= (pos>>(i & mask));
    }
    int get(int i) {
        return a[i>>shift] & (pos>>(i & mask));
    }
    void clr(int i) {
        a[i>>shift] &= ~(pos>>(i & mask));    
    }  
private:
    int n;
    const int mask;
    const int shift;
    const unsigned int pos;
    vector<unsigned int> a;
};
char s[N][N];
BitMap vis(MOD);
int main() {
    scanf("%d %d",&n, &m);
    for (int i = 1; i <= n; ++i) scanf("%s", s[i]+1);
     for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            if(s[i][j] == '1') l[i][j] = l[i][j-1]+1;
        }
        for (int j = m; j >= 1; --j) {
            if(s[i][j] == '1') r[i][j] = r[i][j+1]+1;
        }
    }
    int ans = 0;
     
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            if(s[i][j] == '1') {
                up[i][j] = up[i-1][j]+1;
                if(s[i-1][j] == '1') {
                    l[i][j] = min(l[i-1][j], l[i][j]);
                    r[i][j] = min(r[i-1][j], r[i][j]);
                }
                LL X = i-up[i][j]+1, Y = j-l[i][j]+1, Z = j+r[i][j]-1;
                LL t = (X*3021*3021+Y*3021+Z)%MOD;
                //cout << X << " "<< Y << " " << Z << endl;
                if(!vis.get(t)) vis.set(t), ans++;
            }
        }
    }
    printf("%d\n", ans);
    return 0;
}
View Code

正解代碼:

// #pragma GCC optimize(2)
// #pragma GCC optimize(3)
// #pragma GCC optimize(4)
#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)
 
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
 
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;
 
template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}
 
/**********showtime************/
 
            const int maxn = 3009;
            char str[maxn][maxn];
            int sum[maxn][maxn];
            int dp[maxn][maxn];
            int ls[maxn];
            stack<pii>st;
int main(){
            int n,m;
            scanf("%d%d", &n, &m);
            for(int i=1; i<=n; i++) scanf("%s", str[i] + 1);
            for(int i=1; i<=n; i++) {
                for(int j=1; j<=m; j++) {
                    sum[i][j] = sum[i][j-1];
                    if(str[i][j] == '1') sum[i][j] ++;
                }
            }
 
            for(int i=n; i>=1; i--) {
                for(int j=1; j<=m; j++) {
                    if(str[i][j] == '1') dp[i][j] = dp[i+1][j] + 1;
                    else dp[i][j] = 0;
                }
            }
 
            int ans = 0;
            for(int i=1; i<=n; i++) {
//                debug(i);
                while(!st.empty()) st.pop();
                st.push(pii(-1, 0));
                for(int j=1; j<=m; j++) {
                        while(!st.empty() && st.top().fi >= dp[i][j]) {
                            st.pop();
                        }
                        ls[j] = st.top().se + 1;
                        st.push(pii(dp[i][j], j));
                }
                while(!st.empty()) st.pop();
                 for(int j=1; j<=m + 1; j++) {
                    while(!st.empty() && st.top().fi > dp[i][j]) {
                        int le = ls[st.top().se], ri = j - 1;
                        st.pop();
                        if(sum[i-1][ri] - sum[i-1][le-1] == ri - le + 1) continue;
                        ans++;
                    }
                    if(j < m + 1 && (st.empty() || dp[i][j] > st.top().fi) )st.push(pii(dp[i][j], j));
                }
 
            }
            printf("%d\n", ans);
            return 0;
}
View Code

B

思路:考慮每一個位置的貢獻

代碼:

/*
* @Author: chenkexing
* @Date:   2019-08-10 12:07:44
* @Last Modified by:   chenkexing
* @Last Modified time: 2019-08-10 12:14:56
*/
// #pragma GCC optimize(2)
//  #pragma GCC optimize(3)
//  #pragma GCC optimize(4)
#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)
  
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
  
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;
  
template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}
  
/**********showtime************/
 
            const int maxn = 1e5+9;
            int a[maxn];
            int pre[maxn], las[maxn];
            int le[maxn],ri[maxn];
int main(){
            int n; 
            scanf("%d", &n);
            for(int i=1; i<=n; i++) scanf("%d", &a[i]), las[i] = n + 1;
            ll sum = 0;
            for(int i=1; i<=n; i++) {
                le[i] = pre[a[i]] + 1;
                sum = sum + 1ll*(i - le[i] + 1) * (n - i + 1);
                pre[a[i]] = i;
            }
            printf("%lld\n", sum);
            return 0;
}
View Code

C

思路:構造。左上角、右上角、左下角原矩陣,右下角相反矩陣。cf原題。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
int dp[1055][1055];
int main() {
    dp[0][0]=1;
    int t=10;
    int c=1;
    while(t--) {
        for(int i=0;i<c;i++) {
            for(int j=0;j<c;j++) {
                dp[i][j+c]=dp[i][j];
                dp[i+c][j]=dp[i][j];
                dp[i+c][j+c]=-dp[i][j];
            }
        }
        c<<=1;
    }
    int m;
    scanf("%d", &m);
    for (int i = 0; i < m; ++i) {
        for(int j = 0; j < m; ++j) printf("%d%c", dp[i][j], " \n"[j+1==m]);
    }
    return 0;
}
View Code

D

思路:按期重構

隊友代碼:

/*
* @Author: chenkexing
* @Date:   2019-08-11 21:48:52
* @Last Modified by:   chenkexing
* @Last Modified time: 2019-08-11 23:23:57
*/
 
// #pragma GCC optimize(2)
// #pragma GCC optimize(3)
// #pragma GCC optimize(4)
#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)
 
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<int, pii> p3;
typedef pair<ll, ll> pll;
 
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;
 
template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}
 
/**********showtime************/
 
            const int maxn = 1e5+9;
            int n,m,h,q;
            int getid(int x, int y, int z) {
                return (z - 1)* (n * m) + (x-1)*m + y;
            }
            vector<int>vx,vy,vz;
            int dis[maxn];
            int xia[8][3] = {{0,0,1},{0,1,0},{1,0,0}, {-1, 0 ,0 }, {0, -1 ,0 }, {0, 0 ,-1 }};
            void rebuild(){
                queue< p3>que;
                for(int i=0; i<vx.size(); i++) {
                        int nx = vx[i];
                        int ny = vy[i];
                        int nz = vz[i];
                        dis[getid(nx, ny, nz)] = 0;
                        que.push(p3(nx, pii(ny, nz)));
                }
                vx.clear();
                vy.clear();
                vz.clear();
                while(!que.empty()) {
                    p3 tmp = que.front(); que.pop();
                    int x = tmp.fi;
                    int y = tmp.se.fi;
                    int z = tmp.se.se;
                    for(int i=0; i<6; i++) {
                        int nx = x + xia[i][0];
                        int ny = y + xia[i][1];
                        int nz = z + xia[i][2];
                        if(nx <= 0 || nx > n || ny <= 0|| ny > m || nz <= 0 || nz > h) continue;
                        if(dis[getid(nx, ny, nz)] > dis[getid(x, y, z)] + 1) {
                            dis[getid(nx, ny, nz)] = dis[getid(x, y, z)] + 1;
                            que.push(p3(nx, pii(ny, nz)));
                        }
                    }
                }
 
            }
int main(){
            scanf("%d%d%d%d", &n, &m, &h, &q); 
            int E = sqrt(n * m * h) + 1;
            memset(dis, inf, sizeof(dis));
 
            while(q--) {
                int op, x, y, z;
                scanf("%d%d%d%d", &op, &x, &y, &z);
                if(op == 1) {
                    vx.pb(x);
                    vy.pb(y);
                    vz.pb(z);
                }
                else {
                    int ans = dis[getid(x, y, z)];
                    for(int i=0; i<vx.size(); i++) {
                        int nx = vx[i];
                        int ny = vy[i];
                        int nz = vz[i];
                        ans = min(ans, abs(nx - x) + abs(ny - y) + abs(nz - z));
                    }
                    printf("%d\n", ans);
                }
                if(vx.size() >= E) rebuild();
            }
            return 0;
}
View Code

E

思路:按sz分治,把邊按sz放到劃分樹上,而後分治,用可撤銷並查集維護連通性。和P2147 [SDOI2008]洞穴勘測相似。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
const int N = 1e5 + 5;
struct UFS {
    stack<pair<int*, int>> stk;
    int fa[N], rnk[N];
    inline void init(int n) {
        for (int i = 0; i <= n; ++i) fa[i] = i, rnk[i] = 0;
    }
    inline int Find(int x) {
        while(x^fa[x]) x = fa[x];
        return x;
    }
    inline void Merge(int x, int y) {
        x = Find(x), y = Find(y);
        if(x == y) return ;
        if(rnk[x] <= rnk[y]) {
            stk.push({fa+x, fa[x]});
            fa[x] = y;
            if(rnk[x] == rnk[y]) {
                stk.push({rnk+y, rnk[y]});
                rnk[y]++;
            }
        }
        else {
            stk.push({fa+y, fa[y]});
            fa[y] = x;
        }
    }
    inline void Undo() {
        *stk.top().fi = stk.top().se;
        stk.pop();
    }
}ufs;
struct Node {
    int u, v, l, r;
}a[N];
int n, m, ans;
vector<pii> vc[N<<3];
vector<int> vv;
void update(int L, int R, pii p, int rt, int l, int r) {
    if(L <= l && r <= R) {
        vc[rt].pb(p);
        return ;
    }
    int m = l+r >> 1;
    if(L <= m) update(L, R, p, ls);
    if(R > m)  update(L, R, p, rs);
}
inline int get_id(int x) {
    return lower_bound(vv.begin(), vv.end(), x)-vv.begin();
}
void dfs(int rt, int l, int r) {
    int sz = ufs.stk.size();
    for (pii p : vc[rt]) ufs.Merge(p.fi, p.se);
    if(l == r){
        if(ufs.Find(1) == ufs.Find(n)) ans += vv[l+1]-vv[l];
        while(ufs.stk.size() > sz) ufs.Undo();
        return ;
    }
    int m = l+r >> 1;
    dfs(ls);
    dfs(rs);
    while(ufs.stk.size() > sz) ufs.Undo();
}
int main() {
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= m; ++i) scanf("%d %d %d %d", &a[i].u, &a[i].v, &a[i].l, &a[i].r), ++a[i].r, vv.pb(a[i].l), vv.pb(a[i].r);
    sort(vv.begin(), vv.end());
    vv.erase(unique(vv.begin(), vv.end()), vv.end());
    int tot = vv.size();
    for (int i = 1; i <= m; ++i) {
        update(get_id(a[i].l), get_id(a[i].r)-1, {a[i].u, a[i].v}, 1, 0, tot-2);
    }
    ufs.init(n);
    dfs(1, 0, tot-2);
    printf("%d\n", ans);
    return 0;
}
View Code

F

思路:枚舉中心點,而後極角排序,而後將中心點當作原點,而後三角形的三個點只有兩種狀況:x軸上面2個點,下面1個點,x軸上面1個點,下面2個點

隊友代碼:

#include<bits/stdc++.h>
using namespace std;
struct Point{
    double x,y;
    double t;
    Point(){ x=0,y=0; }
    Point(double _x,double _y):x(_x),y(_y){}
    double operator ^(const Point &b)const{     return x*b.y-y*b.x;}//叉積
    double operator *(const Point &b)const{     return x*b.x+y*b.y;} //點積
    Point operator +(const Point &b)const {     return Point(x+b.x,y+b.y);}
    Point operator -(const Point &b)const {     return Point(x-b.x,y-b.y);}
    Point operator *(double a)            {     return Point(x*a,y*a);    }
    Point operator /(double a)            {     return Point(x/a,y/a);    }
    double polar(){  return atan2(y,x);  }//向量的極角   //返回與x軸正向夾角(-pi~pi]
};
inline double cross(Point a,Point b)    {   return a.x*b.y-a.y*b.x;                             } //叉積
#define ll long long
const int maxn=1e3+10;
const double eps=1e-12;
Point a[maxn];
Point b[maxn];
int s[maxn];
int n;
ll ans=0;
bool cmp1(Point a, Point b)//先按象限排序,再按極角排序,再按遠近排序
{
    if (a.y == 0 && b.y == 0 && a.x*b.x <= 0)return a.x>b.x;
    if (a.y == 0 && a.x >= 0 && b.y != 0)return true;
    if (b.y == 0 && b.x >= 0 && a.y != 0)return false;
    if (b.y*a.y <= 0)return a.y>b.y;
    Point one;
    one.y = one.x = 0;
    return cross(one-a,one-b) > 0 || (cross(one-a,one-b) == 0 && a.x < b.x);
}
void slove(int x){
    for(int i=1;i<=n;i++) { b[i]=a[i]; if(i==x) swap(b[i],b[1]); }
    for(int i=2;i<=n;i++)
    {
        b[i]=b[i]-a[x];
        if(fabs(b[i].x)<eps)  b[i].x=fabs(b[i].x);
        if(fabs(b[i].y)<eps)  b[i].y=fabs(b[i].y);
    }
    for(int i=1;i<=n;i++) { b[i].t= b[i].polar();                }
    sort(b+2,b+1+n,cmp1);
    int c=n;
    while(c>1 && b[c].y<=0 )   c--;
    memset(s,0,sizeof(s));
    int temp=0;
    int j=c;
    for(int i=n;i>c;i--){
        while(j>1 && (b[i]^b[j])<0 ) {  j--; temp++; }
        s[i]=s[i+1]+temp;
    }
    j=c+1;
    for(int i=2;i<=c;i++){
        while(j<=n && (b[i]^b[j])>0 ) { j++; }
        int num=j;
        while(j<=n && (b[i]^b[j])>=0) { j++; }
        ans+=(n-j+1)*(num-c-1)+s[j];
        j=num;
    }
}
int main(){  //printf("%.10f",atan2(0.0000000000,-1000000000.0) );
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%lf %lf",&a[i].x,&a[i].y);
    for(int i=1;i<=n;i++) { slove(i); }
    printf("%lld\n",ans);
}
View Code

G

思路:棧模擬。

代碼:

#include<bits/stdc++.h>
using namespace std;
int main(){
    string ss; cin>>ss;
    int ans=0;
    stack<char> st;
    for(int i=0;i<ss.size();i++){
        if(st.size()<=1){
            st.push(ss[i]);
        }
        else {
            char x=ss[i];
            char y=st.top(); st.pop();
            char z=st.top(); st.pop();
            if(x==y && y==z){
                ans++;
            }
            else {
                st.push(z);
                st.push(y);
                st.push(x);
            }
        }
    }
    cout<<ans<<endl;
}
View Code

H

I

思路:dfs序+掃描線

代碼:

// #pragma GCC optimize(2)
// #pragma GCC optimize(3)
// #pragma GCC optimize(4)
#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)
 
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
 
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
 
template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}
/**********showtime************/
 
            const int maxn = 3e5+9;
 
            int le[maxn],ri[maxn];
            vector<int>mp[maxn];
            int id[maxn], dfn[maxn], tim = 0, sz[maxn];
            void dfs(int u) {
                dfn[u] = ++tim;
                id[tim] = u;
                sz[u] = 1;
                for(int v : mp[u]) {
                    dfs(v);
                    sz[u] += sz[v];
                }
            }
            struct node{
                int le, ri, id, op;
                node(int Le, int Ri, int Id, int Op){
                    le = Le; ri = Ri; id = Id; op = Op;
                }
            };
            vector<node> g[maxn];
            ll ans[maxn];
            struct TT{
                ll sum[maxn<<2], lazy[maxn<<2];
                void pushdown(int le, int ri, int rt) {
                    lazy[rt<<1] += lazy[rt];
                    lazy[rt<<1|1] += lazy[rt];
                    int mid = (le + ri) >> 1;
                    sum[rt<<1] += 1ll*lazy[rt] * (mid - le + 1);
                    sum[rt<<1|1] += 1ll*lazy[rt] * (ri - mid);
                    lazy[rt] = 0;
                }
                void update(int L, int R, int c, int le, int ri, int rt) {
                    if(le >= L && ri <= R) {
                        sum[rt] += 1ll * c * (ri - le + 1);
                        lazy[rt] += 1ll * c;
                        return ;
                    }
                    int mid = (le + ri) >> 1;
                    if(lazy[rt]) pushdown(le , ri, rt);
                    if(L <= mid) update(L, R, c, le, mid, rt<<1);
                    if(mid < R) update(L, R, c, mid+1, ri, rt<<1|1);
                    sum[rt] = sum[rt<<1] + sum[rt<<1|1];
                }
                ll query(int L, int R, int le, int ri, int rt) {
                    if(le >= L && ri <= R) {
                        return sum[rt];
                    }
                    int mid = (le + ri) >> 1;
                    if(lazy[rt]) pushdown(le, ri, rt);
                    ll res = 0;
                    if(L <= mid) res += query(L, R, le, mid, rt<<1);
                    if(mid < R) res += query(L, R, mid+1, ri,rt<<1|1);
                    return res;
                }
            } tree;
int main(){
            int n,m;
            scanf("%d%d", &n, &m);
            le[1] = 1, ri[1] = n;
            for(int i=1; i<=m; i++) {
                int u,v,l,r;
                scanf("%d%d%d%d", &u, &v, &l, &r);
                mp[u].pb(v);
                le[v] = l, ri[v] = r;
            }
            int N = m + 1;
            dfs(1);
 
            int q;  scanf("%d", &q);
            for(int i=1; i<=q; i++) {
                int u, le, ri;
                scanf("%d%d%d", &u, &le, &ri);
                int t1 = dfn[u] - 1;
                g[t1].pb(node(le, ri, i, -1));
                g[t1 + sz[u]].pb(node{le, ri, i, 1});
            }
 
            for(int i=1; i<=tim; i++) {
                int u = id[i];
                tree.update(le[u], ri[u], 1, 1, n, 1);
                for(node a : g[i]) {
                    ans[a.id] += 1ll * a.op * tree.query(a.le, a.ri, 1, n, 1);
                }
            }
 
            for(int i=1; i<=q; i++) printf("%lld\n", ans[i]);
            return 0;
}
View Code

J

隊友補了

2019牛客暑期多校訓練營(第九場)

題號 標題 團隊的狀態
A The power of Fibonacci 未經過
B Quadratic equation  經過
C Inversions of all permutations 未經過
D Knapsack Cryptosystem  經過
E All men are brothers  經過
F Birthday Reminders 未經過
G Checkers 未經過
H Cutting Bamboos  經過
I KM and M 未經過
J Symmetrical Painting  經過

A

B

思路:二次剩餘

代碼:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int p=1e9+7;
int quick(int x,int n,int mod){
    int ans=1;
    while(n){
        if(n&1) ans=1ll*ans*x%mod;
        x=1ll*x*x%mod;
        n=n/2;
    } return ans;
}
int judge(int n,int p) {// p==2 直接 是n    // x*x=n (mod p); (p是奇素數)
    int k=quick(n,(p-1)/2,p);
    if(k==0){  return 0;  } // n==0;  YES;
    if(k==1){  return 1;  } // 1   ;  YES;
    return -1;              // -1  ;  NO;
}
ll w;
struct node{ ll x,y; };
node mul(node a,node b,ll p) {
    node ans={0,0};
    ans.x=((a.x*b.x%p+a.y*b.y%p*w%p)%p+p)%p;
    ans.y=((a.x*b.y%p+a.y*b.x%p)%p+p)%p;
    return ans;
}
ll powwi(node a,ll b,ll p){  // pow
    node ans={1,0};
    while(b){
        if(b&1)ans=mul(ans,a,p);
        a=mul(a,a,p);
        b>>=1;
    }
    return ans.x%p;
}
ll slove(ll n,ll p){
    n%=p; ll a;
    while(1){
        a=rand()%p;
        w=((a*a%p-n)%p+p)%p;
        if(quick(w,(p-1)/2,p)==p-1)break;
    }
    node x={a,1};
    return powwi(x,(p+1)/2,p);
}
int main(){
    int T; scanf("%d",&T);
    while(T--){
        ll b,c; scanf("%lld %lld",&b,&c);
        int x=((1ll*b*b-4*c)%p+p)%p;
        int flag=judge(x,p);
        ll aa,bb;
        if(flag==-1){
            printf("-1 -1\n"); continue;
        }
        else if(flag==0){
            aa=0; bb=p;
        }
        else {
            int cc=slove(x,p);
            aa=min(cc,p-cc);
            bb=max(cc,p-cc);
        }
        if( (b+aa)%2==1 && (b+bb)%2==1) { printf("-1 -1\n"); continue; }
        if( (b+aa)%2==0){
            int x=(b+aa)/2;x=(x%p+p)%p;
            int xx=min(1ll*x,((b-x)%p+p)%p);
            int yy=max(1ll*x,((b-x)%p+p)%p);
            printf("%d %d\n",xx,yy);
        }
        else {
            int x=(b+bb)/2;  x=(x%p+p)%p;
            int xx=min(1ll*x,((b-x)%p+p)%p);
            int yy=max(1ll*x,((b-x)%p+p)%p);
            printf("%d %d\n",xx,yy);
        }
 
    }
}
View Code

C

D

思路:折半枚舉

代碼:

#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
using namespace std;
const int maxn=100;
map<ll,int> mp;
ll a[maxn];
int main(){
    int n; scanf("%d",&n); ll  s; scanf("%lld",&s);
    for(int i=0;i<n;i++) scanf("%lld",&a[i]);
 
    if(n==1){
        if(a[0]==s) printf("1");
        else        printf("0");
            return 0;
    }
    int x=n/2;
    int y=n-x;
    int up=(1<<x);
    for(int i=0;i<up;i++){
        ll temp=0;
        for(int j=0;j<x;j++){
            if(i&(1<<j)){ temp+=a[j]; }
        }
        mp[temp]=i;
    }
    up=(1<<y);
    int ansx=0;
    int ansy=0;
    for(int i=0;i<up;i++){
        ll temp=0;
        for(int j=0;j<y;j++){
            if(i&(1<<j)){ temp+=a[j+x]; }
        }
        if(temp<=s && mp.find(s-temp)!=mp.end()){
            ansx=mp[s-temp];
            ansy=i;
            break;
        }
    }
  //  cout<<ansx<<" "<<ansy<<endl;
    for(int i=0;i<x;i++){
        if(ansx&(1ll<<i)){
            printf("1");
        }else {
            printf("0");
        }
    }
    for(int i=0;i<y;i++){
        if(ansy&(1ll<<i)){
            printf("1");
        }else {
            printf("0");
        }
    }
}
View Code

E

思路:考慮每加一條邊對答案的貢獻。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
const int N = 1e5 + 5;
int fa[N], n, m, x, y;
LL sz[N];
int Find(int x) {
    if(x == fa[x]) return x;
    else return fa[x] = Find(fa[x]);
}
int main() {
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; ++i) fa[i] = i, sz[i] = 1;
    LL d[4] = {n, n-1, n-2, n-3};
    LL ans = 1;
    for (int i = 0; i < 4; ++i) if(d[i]%2 == 0) {d[i] /= 2; break;}
    for (int i = 0; i < 4; ++i) if(d[i]%2 == 0) {d[i] /= 2; break;}
    for (int i = 0; i < 4; ++i) if(d[i]%2 == 0) {d[i] /= 2; break;}
    for (int i = 0; i < 4; ++i) if(d[i]%3 == 0) {d[i] /= 3; break;}
    for (int i = 0; i < 4; ++i) ans = ans*d[i];
    LL sum = n*1LL*(n-1)/2;
    for (int i = 1; i <= m; ++i) {
        printf("%lld\n", ans);
        scanf("%d %d", &x, &y);
        x = Find(x);
        y = Find(y);
        if(x == y) continue;
        sum -= sz[x]*1LL*(n-sz[x]);
        sum -= sz[y]*1LL*(n-sz[y]);
        sum += sz[x]*1LL*sz[y];
        ans -= sz[x]*1LL*sz[y]*sum;
        sz[y] += sz[x];
        sum += sz[y]*1LL*(n-sz[y]);
        fa[x] = y;
    }
    printf("%lld\n", ans);
    return 0;
}
View Code

F

G

H

思路:二分+主席樹

代碼:

/*
* @Author: chenkexing
* @Date:   2019-08-14 21:32:30
* @Last Modified by:   chenkexing
* @Last Modified time: 2019-08-15 00:03:11
*/
// #pragma GCC optimize(2)
// #pragma GCC optimize(3)
// #pragma GCC optimize(4)
#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
#include <unordered_map>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)
 
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
 
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;
 
template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}
/**********showtime************/
 
            const int N = 2e5 + 5, M = 4e6 + 5;//M爲節點個數,爲Q*log(N)
            int root[N], lson[M], rson[M], value[M], tot = 0;
            ll sum[M];
            const double eps = 1e-7;
            //建樹
            void build(int &x, int l, int r) {
                x = ++tot;
                value[x] = 0;
                sum[x] = 0;
                if(l == r) {
                    return ;
                }
                int m = (l+r) >> 1;
                build(lson[x], l, m);
                build(rson[x], m+1, r);
                value[x] = value[lson[x]] + value[rson[x]];
            }
            // 將某個歷史版本p位置的值加v
            void update(int old, int &x, int p, int v, int l, int r) {
                x = ++tot;
                lson[x] = lson[old], rson[x] = rson[old], value[x] = value[old] + v, sum[x] = sum[old] + p;
                if(l == r) return ;
                int m = (l+r) >> 1;
                if(p <= m) update(lson[x], lson[x], p, v, l, m);
                else update(rson[x], rson[x], p, v, m+1, r);
            }
            //訪問某個歷史版本L到R的區間和
            int query(int L, int R, int x, int l, int r) {
                if(L <= l && r <= R) return value[x];
                int m = (l+r) >> 1, ans = 0;
                if(L <= m) ans += query(L, R, lson[x], l, m);
                if(R > m) ans += query(L, R, rson[x], m+1, r);
                return ans;
            }
            ll query2(int L, int R, int x, int l, int r) {
                if(L <= l && r <= R) return sum[x];
                int m = (l+r) >> 1;
                ll ans = 0;
                if(L <= m) ans += query2(L, R, lson[x], l, m);
                if(R > m) ans += query2(L, R, rson[x], m+1, r);
                return ans;
            }
            const int maxn = 2e5+9;
            ll pre[maxn], a[maxn];
            double cal(double val, int L, int R) {
                int hi = floor(val);
                int cnt = query(0, hi, root[R], 0, 100000) - query(0, hi, root[L-1], 0, 100000);
                double ss =  (R - L + 1 - cnt) * val;
                ss += 1.0*query2(0, hi,root[R], 0, 100000) - query2(0, hi, root[L-1], 0, 100000);
                return ss;
            }
int main(){
            int n,m;
            scanf("%d%d", &n, &m);
            build(root[0], 0, 100000);
            for(int i=1; i<=n; i++) {
                scanf("%lld", &a[i]), pre[i] = pre[i-1] + a[i];
                update(root[i-1], root[i], a[i], 1, 0, 100000);
            }
            while(m--) {
                int L, R, x, y;
                scanf("%d%d%d%d", &L, &R, &x, &y);
                ll ss = pre[R] - pre[L-1];
                double nd = ss*1.0 / y *(y - x);
                double le = 0, ri = 1000000005, res = 0;
                //debug(nd);
                while(le + eps < ri) {
                    double mid = (le + ri) / 2;
                    if(cal(mid, L, R) <= nd) le = mid, res = mid;
                    else ri = mid;
                }
                printf("%.10f\n", res);
            }
            return 0;
}
View Code

I

J

思路:差分

代碼:

/*
* @Author: chenkexing
* @Date:   2019-08-16 15:34:14
* @Last Modified by:   chenkexing
* @Last Modified time: 2019-08-16 15:41:12
*/
 
// #pragma GCC optimize(2)
// #pragma GCC optimize(3)
// #pragma GCC optimize(4)
#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)
 
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
 
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
 
template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}
 
/**********showtime************/
            const int maxn = 300009;
            pii a[maxn * 3];
 
int main(){
            int n; 
            scanf("%d", &n);
            int tot = 0;
            for(int i=1; i<=n; i++) {
                int le,ri;
                scanf("%d%d", &le, &ri);
                a[++tot] = pii(2*le, 1);
                a[++tot] = pii(le + ri, -2);
                a[++tot] = pii(2*ri, 1);
            }
            sort(a+1, a+1+tot);
            ll ans = 0, sum = 0;
            ll cnt = a[1].se;
            for(int i=2; i<=tot; i++) {
                sum += cnt * (a[i].fi - a[i-1].fi);
                ans = max(ans, sum);
                cnt += a[i].se;
            }
            printf("%lld\n", ans);
            return 0;
}
View Code

2019牛客暑期多校訓練營(第十場)

題號 標題 團隊的狀態
A Blackjack  經過
B Coffee Chicken  經過
C Gifted Composer 未經過
D Han Xin and His Troops  經過
E Hilbert Sort  經過
F Popping Balloons  經過
G Road Construction  經過
H Stammering Chemists  經過
I Travel Dream 未經過
J Wood Processing  經過

A

隊友補了

B

思路:遞歸

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
LL f[100] = {0, 6, 7}; //57
LL up = 2e12;
int T, n;
string s = "0COFFEE";
string t = "0CHICKEN";
LL k;
void dfs(int x, LL L, LL R) {
    if(R > f[x]) R = f[x];
    if(L > R) return ;
    if(x == 1) {
        for (int i = L; i <= R; ++i) putchar(s[i]);
    }
    else if(x == 2) {
        for (int i = L; i <= R; ++i) putchar(t[i]);
    }
    else {
        if(L > f[x-2]) {
            dfs(x-1, L-f[x-2], R-f[x-2]);
        }
        else if(R > f[x-2]) {
            dfs(x-2, L, f[x-2]);
            dfs(x-1, 1, R-f[x-2]);
        }
        else {
            dfs(x-2, L, R);
        }
    }
}
int main() {
    for (int i = 3; i < 100; ++i) {
        f[i] = f[i-1]+f[i-2];
        if(f[i] > up) break;
    }
    scanf("%d", &T);
    while(T--) {
        scanf("%d %lld", &n, &k);
        if(n%2) dfs(min(57, n), k, k+9);
        else dfs(min(56, n), k, k+9);
        puts("");
    }
    return 0;
}
View Code

C

D

思路:大數寫擴展中國剩餘定理

代碼:

import java.math.BigInteger;
import java.util.*;
 
public class Main {
 
    /**
     * @param args
     */
    static BigInteger x;
    static BigInteger y;
    public static BigInteger exgcd(BigInteger a, BigInteger b) {
        if(b.compareTo(BigInteger.ZERO) == 0){
            x = BigInteger.ONE;
            y = BigInteger.ZERO;
            return a;
        }
        BigInteger gcd = exgcd(b, a.remainder(b));
        BigInteger t = x;
        x = y;
        y = t.subtract(a.divide(b).multiply(y));
        return gcd;
    }
    public static void main(String[] args) {
        Scanner reader = new Scanner(System.in);
        int a[] = new int[105];
        int b[] = new int[105];
        int n = reader.nextInt();
        BigInteger m = reader.nextBigInteger();
        for (int i = 1; i <= n; ++i) {
            b[i] = reader.nextInt();
            a[i] = reader.nextInt();
        }
        BigInteger M = BigInteger.valueOf(b[1]), ans = BigInteger.valueOf(a[1]);
        boolean f = true;
        for (int i = 2; i <= n; ++i) {
            BigInteger A = M, B = BigInteger.valueOf(b[i]), C = (BigInteger.valueOf(a[i]).subtract(ans)).remainder(B);
            C = C.add(B).remainder(B);
            BigInteger gcd = exgcd(A, B), bg = B.divide(gcd);
            if(C.remainder(gcd).compareTo(BigInteger.ZERO) != 0) {
                f = false;
                break;
            }
            x = (x.multiply(C.divide(gcd))).remainder(bg);
            ans = ans.add(x.multiply(M));
            M = M.multiply(bg);
            ans = ans.remainder(M);
        }
        ans = (ans.remainder(M).add(M)).remainder(M);
        if(f == false) System.out.println("he was definitely lying");
        else if(ans.compareTo(m) > 0) System.out.println("he was probably lying");
        else System.out.println(ans);
    }
 
}
View Code

E

思路:遞歸

代碼:

#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
#include <unordered_map>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)
 
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
 
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
 
template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}
/**********showtime************/
            const int maxn = 1e6+9;
            pii a[maxn];
            ll ksm(ll a, ll b) {
                ll res = 1;
                while(b > 0) {
                    if(b & 1) res = res * a;
                    a = a * a;
                    b >>= 1;
                }
                return res;
            }
            vector<pii>ans;
            void dfs(int pt, int inv ,vector<pii>vec, int k, int xbase, int ybase){
                if(vec.size() == 0) return;
                if(vec.size() == 1) {
                    for(pii p : vec) ans.pb(p);
                    return;
                }
                if(k == 0){
                    for(pii p : vec) ans.pb(p);
                    return;
                }
                vector<pii>v[5];
                int mid = ksm(2 , k-1);
                for(pii t : vec) {
                    int x = t.fi, y = t.se;
                    x -= xbase, y -= ybase;
                    if(x <= mid && y <= mid) v[1].pb(t);
                    else if(x > mid && y <= mid) v[2].pb(t);
                    else if(x > mid && y > mid)  v[3].pb(t);
                    else v[4].pb(t);
                }
 
                if(pt == 1) {
                    if(inv){
                        dfs(4, inv ^ 1, v[4], k-1, xbase, ybase + mid);
                        dfs(1, inv, v[3], k-1, xbase+mid, ybase + mid);
                        dfs(1, inv, v[2], k-1, xbase+mid, ybase);
                        dfs(2, inv ^ 1, v[1], k-1,xbase, ybase);
                    }
                    else {
                        dfs(2, inv ^ 1, v[1], k-1,xbase, ybase);
                        dfs(1, inv, v[2], k-1,xbase+mid, ybase);
                        dfs(1, inv, v[3], k-1,xbase+mid, ybase + mid);
                        dfs(4, inv ^ 1, v[4], k-1, xbase, ybase + mid);
                    }
                }
                else if(pt == 2){
                    if(inv) {
                        dfs(1, inv ^ 1, v[1], k-1,xbase, ybase);
                        dfs(2, inv, v[4], k-1, xbase, ybase + mid);
                        dfs(2, inv, v[3], k-1,xbase+mid, ybase + mid);
                        dfs(3, inv ^ 1, v[2], k-1,xbase+mid, ybase);
                    }
                    else {
                        dfs(3, inv ^ 1, v[2], k-1,xbase+mid, ybase);
                        dfs(2, inv, v[3], k-1,xbase+mid, ybase + mid);
                        dfs(2, inv, v[4], k-1, xbase, ybase + mid);
                        dfs(1, inv ^ 1, v[1], k-1,xbase, ybase);
                    }
                }
                else if(pt == 3) {
                    if(inv) {
                        dfs(2, inv ^ 1, v[2], k-1,xbase+mid, ybase);
                        dfs(3, inv, v[1], k-1,xbase, ybase);
                        dfs(3, inv, v[4], k-1,xbase, ybase + mid);
                        dfs(4, inv ^ 1, v[3], k-1,xbase+mid, ybase + mid);
                    }
                    else {
                        dfs(4, inv ^ 1, v[3], k-1,xbase+mid, ybase + mid);
                        dfs(3, inv, v[4], k-1, xbase, ybase + mid);
                        dfs(3, inv, v[1], k-1,xbase, ybase);
                        dfs(2, inv ^ 1, v[2], k-1,xbase+mid, ybase);
                    }
                }
                else {
                    if(inv) {
                        dfs(3, inv ^ 1, v[3], k-1,xbase+mid, ybase + mid);
                        dfs(4, inv, v[2], k-1,xbase+mid, ybase);
                        dfs(4, inv, v[1], k-1,xbase, ybase);
                        dfs(1, inv ^ 1, v[4], k-1, xbase, ybase + mid);
                    }
                    else {
                        dfs(1, inv ^ 1, v[4], k-1, xbase, ybase + mid);
                        dfs(4, inv, v[1], k-1,xbase, ybase);
                        dfs(4, inv, v[2], k-1,xbase+mid, ybase);
                        dfs(3, inv ^ 1, v[3], k-1,xbase+mid, ybase + mid);
                    }
                }
            }
int main(){
            int n, k;
            scanf("%d%d", &n, &k);
            vector<pii>in;
            for(int i=1; i<=n; i++) {
                int x,y;
                scanf("%d%d", &x, &y);
                in.pb(pii(x, y));
            }
            dfs(1, 0, in, k, 0, 0);
            for(pii p : ans) {
                printf("%d %d\n", p.fi, p.se);
            }
            return 0;
}
View Code

F

思路:暴力+multiset

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
const int N = 1e5 + 1;
multiset<int> s;
vector<int> vc[N];
int n, x, y, r, cnt[N], tot[N];
int main() {
    scanf("%d %d", &n, &r);
    for (int i = 1; i <= n; ++i) {
        scanf("%d %d", &x, &y);
        vc[x].pb(y);
        cnt[y]++;
    }
    for (int i = 0; i < N; ++i) {
        tot[i] = cnt[i];
        if(i+r < N) tot[i] += cnt[i+r];
        if(i+r+r < N) tot[i] += cnt[i+r+r];
        s.insert(tot[i]);
    }
    int ans = 0;
    for (int x = 0; x < N; ++x) {
        int tmp = vc[x].size();
        if(x+r < N) tmp += vc[x+r].size();
        if(x+r+r < N) tmp += vc[x+r+r].size();
        for (int y : vc[x]) {
            if(y-r >= 0) {
                int t = tot[y-r];
                s.erase(s.find(t));
                s.insert(t-1);
                tot[y-r]--;
            }
            {
                int t = tot[y];
                s.erase(s.find(t));
                s.insert(t-1);
                tot[y]--;
            }
            if(y-2*r >= 0) {
                int t = tot[y-r-r];
                s.erase(s.find(t));
                s.insert(t-1);
                tot[y-r-r]--;
            }
        }
        if(x+r < N)
        for (int y : vc[x+r]) {
            if(y-r >= 0) {
                int t = tot[y-r];
                s.erase(s.find(t));
                s.insert(t-1);
                tot[y-r]--;
            }
            {
                int t = tot[y];
                s.erase(s.find(t));
                s.insert(t-1);
                tot[y]--;
            }
            if(y-2*r >= 0) {
                int t = tot[y-r-r];
                s.erase(s.find(t));
                s.insert(t-1);
                tot[y-r-r]--;
            }
        }
        if(x+r+r < N)
        for (int y : vc[x+r+r]) {
            if(y-r >= 0) {
                int t = tot[y-r];
                s.erase(s.find(t));
                s.insert(t-1);
                tot[y-r]--;
            }
            {
                int t = tot[y];
                s.erase(s.find(t));
                s.insert(t-1);
                tot[y]--;
            }
            if(y-2*r >= 0) {
                int t = tot[y-r-r];
                s.erase(s.find(t));
                s.insert(t-1);
                tot[y-r-r]--;
            }
        }
        tmp += *s.rbegin();
        ans = max(ans, tmp);
        for (int y : vc[x]) {
            if(y-r >= 0) {
                int t = tot[y-r];
                s.erase(s.find(t));
                s.insert(t+1);
                tot[y-r]++;
            }
            {
                int t = tot[y];
                s.erase(s.find(t));
                s.insert(t+1);
                tot[y]++;
            }
            if(y-2*r >= 0) {
                int t = tot[y-r-r];
                s.erase(s.find(t));
                s.insert(t+1);
                tot[y-r-r]++;
            }
        }
        if(x+r < N)
        for (int y : vc[x+r]) {
            if(y-r >= 0) {
                int t = tot[y-r];
                s.erase(s.find(t));
                s.insert(t+1);
                tot[y-r]++;
            }
            {
                int t = tot[y];
                s.erase(s.find(t));
                s.insert(t+1);
                tot[y]++;
            }
            if(y-2*r >= 0) {
                int t = tot[y-r-r];
                s.erase(s.find(t));
                s.insert(t+1);
                tot[y-r-r]++;
            }
        }
        if(x+r+r < N)
        for (int y : vc[x+r+r]) {
            if(y-r >= 0) {
                int t = tot[y-r];
                s.erase(s.find(t));
                s.insert(t+1);
                tot[y-r]++;
            }
            {
                int t = tot[y];
                s.erase(s.find(t));
                s.insert(t+1);
                tot[y]++;
            }
            if(y-2*r >= 0) {
                int t = tot[y-r-r];
                s.erase(s.find(t));
                s.insert(t+1);
                tot[y-r-r]++;
            }
        }
    }
    printf("%d\n", ans);
    return 0;
}
View Code

G

思路:對稱軸必定平行或垂直與任意兩點連線。

代碼:

#include<bits/stdc++.h>
using namespace std;
#define pb emplace_back
const double eps=1e-6;
const int maxn=310;
struct Point{
    double x,y;
    double w;
    Point(){ x=0,y=0; }
    Point(double _x,double _y):x(_x),y(_y){}
};
int n;
Point pa[maxn];
bool up(Point a,Point b){
    return a.w<b.w;
}
bool upx(Point a,Point b){
    return a.x<b.x;
}
bool upy(Point a,Point b){
    return a.y<b.y;
}
double k[maxn*maxn*2];
inline double dis(double b, double k) {
    return b/sqrt(k*k+1.0);
}
inline double solve(double l, double r, double k) {
    return dis(r-l, k)/2.0;
}
int main(){
    cin >> n;
    for (int i = 1; i <= n; ++i) cin >> pa[i].x >> pa[i].y;
    int tot=0;
    double ans=0;
    for(int i=1;i<=n;i++){
        for(int j=i+1;j<=n;j++){
            if(fabs(pa[i].x-pa[j].x) < eps) continue;
            else if(fabs(pa[i].y-pa[j].y) < eps) continue;
            else {
                k[++tot]=(pa[j].y-pa[i].y)/(pa[j].x-pa[i].x);
                k[++tot] = -(pa[j].x-pa[i].x)/(pa[j].y-pa[i].y);
            }
        }
    }
    sort(pa+1,pa+1+n,upx);
    ans=max((pa[n/2+1].x-pa[n/2].x)/2,ans);
    sort(pa+1,pa+1+n,upy);
    ans=max((pa[n/2+1].y-pa[n/2].y)/2,ans);
    for (int i = 1; i <= tot; ++i) {
        for (int j = 1; j <= n; ++j) pa[j].w = pa[j].y-k[i]*pa[j].x;
        sort(pa+1, pa+1+n, up);
        ans = max(ans, solve(pa[n/2].w, pa[n/2+1].w, k[i]));
    }
    cout << fixed << setprecision(12) << ans <<endl;
    return 0;
}
View Code

H

思路:水題

代碼:

#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
#include <unordered_map>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)
 
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
 
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
 
template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}
/**********showtime************/
 
            int du[7], cnt[7];
            pii a[7];
 
int main(){
            int T;  scanf("%d", &T);
            while(T--) {
                for(int i=1; i<=6; i++) du[i] = 0, cnt[i] = 0;
 
                for(int i=1; i<=5; i++) {
                    int u,v;
                    scanf("%d%d", &u, &v);
                    du[u] ++; du[v]++;
                    a[i].fi = u, a[i].se = v;
                }
                for(int i=1; i<=6; i++) cnt[du[i]]++;
                if(cnt[2] == 4) puts("n-hexane");
                else if(cnt[4] == 1) puts("2,2-dimethylbutane");
                else if(cnt[3] == 2) puts("2,3-dimethylbutane");
                else {
                    int cc1 = 0;
                    for(int i=1; i<=5; i++) {
                        int u = a[i].fi, v = a[i].se;
                        if(du[u] == 3 && du[v] == 1) cc1++;
                        if(du[v] == 3 && du[u] == 1) cc1++;
                    }
                    if(cc1 == 1) puts("3-methylpentane");
                    else puts("2-methylpentane");
                }
            }
            return 0;
}
View Code

I

J

思路:斜率優化dp,維護遞增斜率$\frac{dp[j]-dp[k]+sum[k]-sum[j]+h[j+1]*sw[j]-h[k+1]*sw[k]}{h[j+1]-h[k+1]}$,其中$sum$是按高度排序後面積的前綴和,$sw$是寬度前綴和。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head
 
const int N = 5e3 + 10, M = 2e3 + 5;
LL sum[N], sw[N], dp[M][N];
int h[N], w[N];
pii a[N];
int n, k;
deque<int> q[M];
LL up(int p, int k, int j) {
    return dp[p][j]-dp[p][k]+sum[k]-sum[j]+h[j+1]*sw[j]-h[k+1]*sw[k];
}
LL dw(int k, int j) {
    return h[j+1]-h[k+1];
}
bool g(int p, int k, int j, LL C) {
    return up(p, k, j) <= C*1.0*dw(k, j);
}
bool gg(int p, int k, int j, int i) {
    return up(p, k, j)*1.0*dw(j, i) >= up(p, j, i)*1.0*dw(k, j);
}
int main() {
    scanf("%d %d", &n, &k);
    for (int i = 1; i <= n; ++i) scanf("%d %d", &a[i].se, &a[i].fi);
    sort(a+1, a+1+n);
    for (int i = 1; i <= n; ++i) h[i] = a[i].fi, w[i] = a[i].se, sw[i] = sw[i-1]+w[i], sum[i] = sum[i-1] + w[i]*1LL*h[i];
    q[0].push_back(0);
    for (int i = 1; i <= n; ++i) {
        for (int j = min(k, i); j >= 1; --j) {
            while(q[j-1].size() >= 2) {
                int a = q[j-1].front();
                q[j-1].pop_front();
                int b = q[j-1].front();
                if(g(j-1, a, b, sw[i])) ;
                else {
                    q[j-1].push_front(a);
                    break;
                }
            }
            if(!q[j-1].empty()) {
                int x = q[j-1].front();
                dp[j][i] = dp[j-1][x] + sum[i]-sum[x]-h[x+1]*(sw[i]-sw[x]);
                 while(q[j].size() >= 2) {
                    int b = q[j].back();
                    q[j].pop_back();
                    int a = q[j].back();
                    if(gg(j, a, b, i)) ;
                    else {
                        q[j].push_back(b);
                        break;
                    }
                }
                q[j].push_back(i);
            }
        }
    }
    printf("%lld\n", dp[k][n]);
    return 0;
}
View Code

杭電

2019 Multi-University Training Contest 1

Solved Pro.ID Title
   1001 Blank
  1002 Operation
   1003 Milk
  1004 Vacation
  1005 Path
  1006 Typewriter
  1007 Meteor
  1008 Desert
  1009 String
  1010 Kingdom
   1011 Function
   1012 Sequence
  1013 Code

1001

思路:dp

$dp[i][j][k][l]$表示每種顏色出現位置分別爲$i$,$j$,$k$,$l$,$i \le j \le k \le l$,其中,等號只有在等於0時才取獲得。

沒必要在乎每種顏色在哪一個位置,只須要知道這四個位置的顏色都是不一樣的。而後考慮轉移到,有以下四種狀態能夠轉移到:

$dp[j][k][l][l+1]$,$dp[i][k][l][l+1]$,$dp[i][j][l][l+1]$,$dp[i][j][k][l+1]$,而後第四個維度滾動數組優化一下

因而時間複雜度$O(C(n, 4))$,空間複雜度$O(n^3)$

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 103;
const int MOD = 998244353;
int dp[N][N][N][2], n, m, l, r, x, T;
vector<int> vc[N][5];
int main() {
    scanf("%d", &T);
    while(T--) {
        scanf("%d %d", &n, &m);
        for (int i = 1; i <= n; ++i) for (int j = 1; j <= 4; ++j) vc[i][j].clear();
        for (int i = 1; i <= m; ++i) scanf("%d %d %d", &l, &r, &x), vc[r][x].pb(l);
        dp[0][0][0][0] = 1;
        int now = 0, ans = 0;
        for (int l = 0; l <= n; ++l) {
            now ^= 1;
            for (int i = 0; i <= l+1; ++i) for (int j = i; j <= l+1; ++j) for (int k = j; k <= l+1; ++k) dp[i][j][k][now] = 0;
            for (int k = l; k >= 0; --k) {
                bool f = false;
                for (int x : vc[l][1]) {
                    if(x <= k) {
                        f = true;
                        break;
                    }
                }
                if(f) continue;
                f = false;
                for (int x : vc[l][2]) {
                    if(x > k) {
                        f = true;
                        break;
                    }
                }
                if(f) break;
                for (int j = k; j >= 0; --j) {
                    bool f = false;
                    for (int x : vc[l][2]) {
                        if(x <= j) {
                            f = true;
                            break;
                        }
                    }
                    if(f) continue;
                    f = false;
                    for (int x : vc[l][3]) {
                        if(x > j) {
                            f = true;
                            break;
                        }
                    }
                    if(f) break;
                    for (int i = j; i >= 0; --i) {
                        bool f = false;
                        for (int x : vc[l][3]) {
                            if(x <= i) {
                                f = true;
                                break;
                            }
                        }
                        if(f) continue;
                        f = false;
                        for (int x : vc[l][4]) {
                            if(x > i) {
                                f = true;
                                break;
                            }
                        }
                        if(f) break;
                        //cout << i << " " << j << " " << k << " " << l << endl;
                        if(l != n) {
                            (dp[j][k][l][now] += dp[i][j][k][now^1]) %= MOD;
                            (dp[i][k][l][now] += dp[i][j][k][now^1]) %= MOD;
                            (dp[i][j][l][now] += dp[i][j][k][now^1]) %= MOD;
                            (dp[i][j][k][now] += dp[i][j][k][now^1]) %= MOD;
                        }
                        else {
                            (ans += dp[i][j][k][now^1]) %= MOD;
                        }
                    }
                }
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}
View Code

1002

思路:線性基+貪心,cf原題,詳見FCY博客

代碼:

using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 1e6 + 3;
int a[N], base[N][30], pos[N][30];
inline void add(int p) {
    int x = a[p];
    int pp = p;
    for (int i = 29; i >= 0; --i) base[p][i] = base[p-1][i], pos[p][i] = pos[p-1][i];
    for (int i = 29; i >= 0; --i) {
        if(x&(1<<i)) {
            if(!base[pp][i]) {
                base[pp][i] = x;
                pos[pp][i] = p;
                return ;
            }
            if(p > pos[pp][i]) swap(base[pp][i], x), swap(pos[pp][i], p);
            x ^= base[pp][i];
        }
    }
}
inline int solve(int L, int R) {
    int res = 0;
    for (int i = 29; i >= 0; --i) {
        if(base[R][i] && pos[R][i] >= L) {

            if((base[R][i]^res) > res) res ^= base[R][i];
        }
    }
    return res;
}
int T, n, m, op, l, r;
int main() {
    scanf("%d", &T);
    while(T--) {
        scanf("%d %d", &n, &m);
        for (int i = 1; i <= n; ++i) scanf("%d", &a[i]), add(i);
        int ans = 0;
        for (int i = 1; i <= m; ++i) {
            scanf("%d", &op);
            if(op == 0) {
                scanf("%d %d", &l, &r);
                l = (l^ans)%n+1;
                r = (r^ans)%n+1;
                if(l > r) swap(l, r);
                ans = solve(l, r);
                printf("%d\n", ans);
            }
            else {
                scanf("%d", &l);
                l ^= ans;
                a[++n] = l;
                add(n);
            }
        }
    }
    return 0;
}
/*
8
8 8
1 2 3 4 5 6 7 8
*/
View Code  

1003

1004

思路:貪心,假設每輛車都跑到最前面,時間取最大值

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 1e5 + 3;
int l[N];
int s[N];
int v[N];
LL  ll[N];

int main(){
    int n;
    while(~scanf("%d",&n)){
        for(int i=0;i<=n;i++) scanf("%d",&l[i]);
        for(int i=0;i<=n;i++) scanf("%d",&s[i]);
        for(int i=0;i<=n;i++) scanf("%d",&v[i]);
        for(int i=1;i<=n;i++){
            ll[i]=ll[i-1]+l[i];
        }
        double ans=0;
        for(int i=n;i>=0;i--){
            ans=max(ans,(ll[i]+s[i])*1.0/v[i]);
        }
        printf("%.10f\n",ans);
    }
}
View Code

1005

思路:先建出從1出發的dijkstra圖,而後在這張圖上跑1到n的最小割。

代碼:

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;


template<class T> void _R(T &x) { cin >> x; }
void _R(int &x) { scanf("%d", &x); }
void _R(ll &x) { scanf("%lld", &x); }
void _R(double &x) { scanf("%lf", &x); }
void _R(char &x) { scanf(" %c", &x); }
void _R(char *x) { scanf("%s", x); }
void R() {}
template<class T, class... U> void R(T &head, U &... tail) { _R(head); R(tail...); }


template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}

const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;

/**********showtime************/
            const int maxn = 10009;
            vector<pii>mp[maxn];
            ll dis[maxn];
                int n,m;
            void dji(int s) {
                priority_queue<pll>que;
                que.push(pll(0, s));
                for(int i=1; i<=n; i++) {
                    dis[i] = inff;
                }
                dis[s] = 0;
                while(!que.empty()) {
                    pll t = que.top(); que.pop();
                    int u = t.se;
                    if(dis[u] < -1ll*t.fi) continue;
                    for(int i=0; i<mp[u].size(); i++) {
                        int v = mp[u][i].fi;
                        int w = mp[u][i].se;
                        if(dis[v] > dis[u] + w) {
                            dis[v] = dis[u] + w;
                            que.push(pll(-1ll*dis[v], v));
                        }
                    }
                }
            }

            struct E{
                int v;
                ll w;
                int nxt;
            }edge[20009];
            int head[maxn], gtot = 0;
            void addedge(int u, int v, ll w) {
                edge[gtot].v = v;
                edge[gtot].w = w;
                edge[gtot].nxt = head[u];
                head[u] = gtot++;

                edge[gtot].v = u;
                edge[gtot].w = 0;
                edge[gtot].nxt = head[v];
                head[v] = gtot++;
            }

            int dd[maxn], cur[maxn];
            bool bfs(int s, int t) {
                for(int i=s; i<=t; i++) cur[i] = head[i], dd[i] = inf;
                queue<int>que;
                que.push(s);
                dd[s] = 0;
                while(!que.empty()) {
                    int u = que.front();
                    que.pop();
                    for(int i=head[u]; ~i; i=edge[i].nxt) {
                        int v = edge[i].v;ll  w = edge[i].w;
                        if(w > 0 && dd[v] > dd[u] + 1) {
                            dd[v] = dd[u] + 1;
                            que.push(v);
                        }
                    }
                }
                return dd[t] < inf;
            }
            ll dfs(int u, int t, ll maxflow) {
                if(u == t || maxflow == 0) return maxflow;
                for(int i=cur[u]; ~i; i=edge[i].nxt) {
                    cur[u] = i;
                    int v = edge[i].v; ll w = edge[i].w;
                    if(dd[v] == dd[u] + 1 && w > 0) {
                        ll f = dfs(v, t, min(maxflow, 1ll*w));
                        if(f > 0) {
                            edge[i].w -= f;
                            edge[i ^ 1].w += f;
                            return f;
                        }
                    }
                }
                return 0;
            }
            ll dinic(int s, int  t){
                ll flow = 0;
                while(bfs(s, t)) {
                    while(ll f = dfs(s, t, inff)) flow += f;
                }
                return flow;
            }
int main(){
            int T;  scanf("%d", &T);
            while(T--) {

                scanf("%d%d", &n, &m);
                gtot = 0;
                for(int i=1; i<=n; i++) mp[i].clear(), head[i] = -1;
                for(int i=1; i<=m; i++) {
                    int u,v,c;
                    scanf("%d%d%d", &u, &v, &c);
                    mp[u].pb(pii(v, c));
                }
                dji(1);
                for(int i=1; i<=n; i++) {
                    int u = i;
                    for(pii p : mp[i]) {
                        int v = p.fi, w = p.se;
                        if(dis[v] == dis[u] + w){
                            addedge(u, v, w);
                        }
                    }
                }
                printf("%lld\n", dinic(1, n));
            }
            return 0;
}
View Code

1006

隊友補了

1007

1008

1009

思路:貪心,每次在能選的字符中選個最小的。用隊列記錄每一個字符的位置,並預處理好每一個位置後面每一個字符的個數。有很一些限制條件,寫起來不簡單。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 1e5 + 5;
char s[N];
queue<int> q[26];
int L[26], R[26], dp[N][26], n, k;
vector<int> vc;
int main() {
    while(~scanf("%s %d", s+1, &k)) {
        int n = strlen(s+1);
        for (int i = 0; i < 26; ++i) scanf("%d %d", &L[i], &R[i]);
        for (int i = 0; i < 26; ++i) dp[n+1][i] = 0;
        for (int i = n; i >= 1; --i) {
            for (int j = 0; j < 26; ++j) dp[i][j] = dp[i+1][j];
            dp[i][s[i]-'a']++;
        }
        for (int i = 0; i < 26; ++i) while(!q[i].empty()) q[i].pop();
        for (int i = 1; i <= n; ++i) q[s[i]-'a'].push(i);
        vc.clear();
        int tot = 0;
        for (int i = 0; i < 26; ++i) tot += L[i];
        while(true) {
            if(vc.size() == k) break;
            bool f = false;
            for (int i = 0; i < 26; ++i) {
                if(!q[i].empty() && R[i] > 0 && tot-L[i] <= k-vc.size()-1) {
                    //cout << i <<endl;
                    bool ff = false;
                    int CC = 0;
                    for (int j = 0; j < 26; ++j) {
                        if(dp[q[i].front()][j] < L[j]) ff = true;
                        CC += min(R[j], dp[q[i].front()][j]);
                    }
                    if(ff) continue;
                    if(CC < k-vc.size()) continue;
                    vc.pb(q[i].front());
                    q[i].pop();
                    f = true;
                    if(L[i]) {
                        L[i]--;
                        tot--;
                    }
                    if(R[i]) R[i]--;
                    break;
                }
            }
            if(!f) break;
            if(!vc.empty())
            for (int i = 0; i < 26; ++i) {
                while(!q[i].empty() && q[i].front() < vc.back()) q[i].pop();
            }
        }
        if(vc.size() != k) printf("-1\n");
        else {
            for (int x : vc) putchar(s[x]);
            puts("");
        }
    }
    return 0;
}
/*
ababababab 10
5 5
5 5
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0
*/
View Code

1010

1011

隊友補了

1012

思路:母函數+NTT

代碼:

#include<bits/stdc++.h>
using namespace std;
#define LL long long

const int N = 400100, P = 998244353;
const int M = 1.2e6;
inline int qpow(int x, int y) {
  int res(1);
  while (y) {
    if (y & 1) res = 1ll * res * x % P;
    x = 1ll * x * x % P;
    y >>= 1;
  }
  return res;
}

int r[N];
void ntt(int *x, int n, int opt) {
  register int i, j, k, m, gn, g, tmp;
  for (i = 0; i < n; ++i)
    if (r[i] < i) swap(x[i], x[r[i]]);
  for (m = 2; m <= n; m <<= 1) {
    k = m >> 1;
    gn = qpow(3, (P - 1) / m);    ///3是原根
    for (i = 0; i < n; i += m) {
      g = 1;
      for (j = 0; j < k; ++j, g = 1ll * g * gn % P) {
        tmp = 1ll * x[i + j + k] * g % P;
        x[i + j + k] = (x[i + j] - tmp + P) % P;
        x[i + j] = (x[i + j] + tmp) % P;
      }
    }
  }
  if (opt == -1) {
    reverse(x + 1, x + n);
    register int inv = qpow(n, P - 2);
    for (i = 0; i < n; ++i) x[i] = 1ll * x[i] * inv % P;
  }
}

int A[N], B[N], C[N], f[M], invf[M], a[N];
int T, nm, q, x, y, z, c;
inline void init() {
    f[0] = 1;
    for (int i = 1; i < M; ++i) f[i] = (f[i-1]*1LL*i)%P;
    invf[M-1] = qpow(f[M-1], P-2);
    for (int i = M-2; i >= 0; --i) invf[i] = invf[i+1]*1LL*(i+1)%P;
}
inline int CC(int n, int m) {
    if(m < 0 || m > n) return 0;
    return (f[n]*1LL*invf[m]%P*1LL*invf[n-m])%P;
}
int main() {
    init();
    scanf("%d", &T);
    while(T--){
        int n, m, L = 0;
        x = y = z = 0;
        scanf("%d %d", &nm, &q);
        for (int i = 0; i < nm; ++i) scanf("%d", &a[i]);
        for (int i = 0; i < q; ++i) {
            scanf("%d", &c);
            if(c == 1) x++;
            else if(c == 2) y++;
            else z++;
        }
        L = 0;
        n = m = nm;
        m = n+m;
        for(n = 1; n <= m; n <<= 1) L++;
        for (int i = 0; i < n; i++) r[i] = (r[i>>1]>>1) | ((i&1) << L-1);
        if(x) {
            for (int i = 0; i < nm; ++i) A[i] = a[i];
            for (int i = 0; i < nm; ++i) B[i] = CC(i+x-1, i);
            ntt(A, n, 1);
            ntt(B, n, 1);
            for (int i = 0; i < n; ++i) C[i] = 1ll * A[i] * B[i] % P;
            ntt(C, n, -1);
            for (int i = 0; i < nm; ++i) a[i] = C[i];
            for (int i = 0; i < n; ++i) A[i] = B[i] = C[i] = 0;
        }
        if(y) {
            for (int i = 0; i < nm; ++i) A[i] = a[i];
            for (int i = 0; 2*i < nm; ++i) B[2*i] = CC(i+y-1, i);
            ntt(A, n, 1);
            ntt(B, n, 1);
            for (int i = 0; i < n; ++i) C[i] = 1ll * A[i] * B[i] % P;
            ntt(C, n, -1);
            for (int i = 0; i < nm; ++i) a[i] = C[i];
            for (int i = 0; i < n; ++i) A[i] = B[i] = C[i] = 0;
        }
        if(z) {
            for (int i = 0; i < nm; ++i) A[i] = a[i];
            for (int i = 0; 3*i < nm; ++i) B[3*i] = CC(i+z-1, i);
            ntt(A, n, 1);
            ntt(B, n, 1);
            for (int i = 0; i < n; ++i) C[i] = 1ll * A[i] * B[i] % P;
            ntt(C, n, -1);
            for (int i = 0; i < nm; ++i) a[i] = C[i];
            for (int i = 0; i < n; ++i) A[i] = B[i] = C[i] = 0;
        }
        LL ans = 0;
        for (int i = 0; i < nm; ++i) ans ^= ((i+1)*1LL*a[i]);
        printf("%lld\n", ans);
    }
    return 0;
}
View Code

1013

思路:假設要求的三個變量爲$(b,w1,w2)$。首先很容易想到$b$只是作一個平移運動,只要原來應該大於0的元素的最小值大於應該小於0的元素的最大值,

就必定能夠找到一個$b$平移全部元素使得大於0的元素大於0,小於0的小於0。因此$b$徹底能夠忽略。那麼就只有兩個變量$w1$,$w2$須要肯定。根據上面

的結論,咱們要找到$w1$,$w2$,使得應該大於0的元素的相對大小大於小於0的。即對於任意$i$,$j$,若是$y_i == 1 且 y_j == -1$,那麼要保證

$w1*x1_i +w2*x2_i > w1*x1_j +w2*x2_j$ 。兩邊同除以$w1$,$x1_i +\frac{w2}{w1}*x2_i > x1_j +\frac{w2}{w1}*x2_j$ ,因此只要肯定一個變量$\frac{w2}{w1}$

就能夠啦,因而$n^2$枚舉,判斷這個變量的存不存在一個可行區間就能夠啦。若是$w1==0$怎麼辦,那麼假設它等於0再判斷一遍,我沒有判也過了。

還有一點,因爲$w1$的正負性不肯定,因此$x1_i$的係數不必定是1,可能仍是-1,兩個都要判一遍。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 105;
const double INF = 1LL<<60;
int T, n;
int x1[N], x2[N], y[N];
int main() {
    scanf("%d", &T);
    while(T--) {
        scanf("%d", &n);
        for (int i = 1; i <= n; ++i) scanf("%d %d %d", &x1[i], &x2[i], &y[i]);
        double L = -(1LL<<60), R =1LL<<60;
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= n; ++j) {
                if(i == j) continue;
                if(y[i] == 1 && y[j] == -1) {
                    if(x2[i] == x2[j]) continue;
                    double d = x2[j]-x2[i];
                    double up = x1[i]-x1[j];
                    if(d < 0) L = max(L, up/d);
                    else R = min(R, up/d);
                }
            }
        }
        if(L <= R) {
            printf("Successful!\n");
            continue;
        }

        L = -(1LL<<60), R =1LL<<60;
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= n; ++j) {
                if(i == j) continue;
                if(y[i] == 1 && y[j] == -1) {
                    if(x2[i] == x2[j]) continue;
                    double d = x2[j]-x2[i];
                    double up = -x1[i]+x1[j];
                    if(d < 0) L = max(L, up/d);
                    else R = min(R, up/d);
                }
            }
        }
        if(L <= R) {
            printf("Successful!\n");
            continue;
        }
        printf("Infinite loop!\n");
    }
    return 0;
}
View Code

2019 Multi-University Training Contest 2

Solved Pro.ID Title
  1001 Another Chess Problem
  1002 Beauty Of Unimodal Sequence
  1003 Coefficient
  1004 Double Tree
  1005 Everything Is Generated In Equal Probability
  1006 Fantastic Magic Cube
  1007 Game
    1008 Harmonious Army
  1009 I Love Palindrome String
  1010 Just Skip The Problem
  1011 Keen On Everything But Triangle
    1012 Longest Subarray

1001

1002

1003

1004

1005

思路:打表找規律

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int MOD = 998244353;
const int N = 3e3 + 10;
LL t[N], s[N];
LL q_pow(LL n, LL k) {
    LL res = 1;
    while(k) {
        if(k&1) res = (res*n)%MOD;
        n = (n*n)%MOD;
        k >>= 1; 
    }
    return res;
}
int n;
int main() {
    t[1] = 0;
    LL now = 2;
    for (int i = 2; i < N; ++i) {
        t[i] = (t[i-1]+now)%MOD;
        now = (now+2)%MOD;
    }
    for (int i = 1; i < N; ++i) s[i] =(s[i-1]+t[i])%MOD;
    while(~scanf("%d", &n)) {
        printf("%lld\n", s[n]*q_pow(3*n, MOD-2)%MOD);
    }
    return 0;
}
View Code

1006

1007

1008

隊友補了

1009

思路:迴文自動機,在迴文樹上dfs,跑一個前綴的正反hash值,而後就能夠判斷每個本質不一樣的迴文串的一半是否是也是迴文串。

隊友代碼:

#include<bits/stdc++.h>
#define ll long long
#define LL long long
using namespace std;
const int maxn=3e5+10;
const int mod=1e9+7;
const int h1=222333;
char ss[maxn];
int a[maxn];
int ha[maxn];
int hb[maxn];
int hh[maxn];
struct PAM{
    #define ll long long
    #define LL long long
    static const int maxn=3e5+10;
    static const int num=27;
    int fail[maxn],cnt[maxn],len[maxn],ch[maxn][num];
    int last,tot;
    LL ans;
    void inint(){
        last=0;  tot=0;
        fail[0]=fail[1]=1;
        len[0]=0; len[1]=-1; tot++;
    }
    int get_fail(int p,int pos){
         while(ss[pos-len[p]-1]!=ss[pos]) p=fail[p];
         return p;
    }
    void add(int x,int pos){
        int p=get_fail(last,pos);
        if(!ch[p][x]){
            len[++tot]=len[p]+2;
            fail[tot]=ch[get_fail(fail[p],pos)][x];
            ch[p][x]=tot; ans++;
        }
        cnt[last=ch[p][x]]++;
    }
    void count(){  //  bu zhi bu tong hui wen ge shu
        for(int i=tot;i>=0;i--){
            cnt[fail[i]]+=cnt[i];
        }
    }
    void dfs(int x,int pos){
        for(int i=0;i<num;i++){
            if(ch[x][i]){
                if(pos==0) ha[pos]=(1ll*i)%mod;
                else       ha[pos]=(1ll*ha[pos-1]*h1+i)%mod;
                if(pos==0) hb[pos]=(1ll*i*hh[pos])%mod;
                else       hb[pos]=(1ll*i*hh[pos]+hb[pos-1])%mod;
                int k=ch[x][i];
                if(ha[pos]==hb[pos]){
                    a[len[k]]+=cnt[k];
                }
                dfs(k,pos+1);

            }
        }
    }
    void work(){
        dfs(0,0);
        dfs(1,0);
    }
    void clear(){
        for(int i=0;i<=tot;i++){
            fail[i]=0; len[i]=0; cnt[i]=0;
            for(int j=0;j<num;j++) ch[i][j]=0;
        }
        last=tot=ans=0;
    }
}pam;
int main(){
    hh[0]=1;  for(int i=1;i<maxn;i++) hh[i]=1ll*hh[i-1]*h1%mod;
    while(~scanf("%s",ss)){
        int l=strlen(ss); pam.inint();  //cout<<l<<endl;
        for(int i=0;i<l;i++)  pam.add(ss[i]-'a',i);
        pam.count();  pam.work();
        for(int i=1;i<=l;i++){
            if(i!=1) printf(" ");
            printf("%d",a[i]); a[i]=0;
        }printf("\n");
        pam.clear();
    }
}
View Code

1010

思路:$n!$,當$n>=mod$時,等於$0$

代碼:

#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;


template<class T> void _R(T &x) { cin >> x; }
void _R(int &x) { scanf("%d", &x); }
void _R(ll &x) { scanf("%lld", &x); }
void _R(double &x) { scanf("%lf", &x); }
void _R(char &x) { scanf(" %c", &x); }
void _R(char *x) { scanf("%s", x); }
void R() {}
template<class T, class... U> void R(T &head, U &... tail) { _R(head); R(tail...); }


template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}

const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e6+3;

/**********showtime************/
            const int maxn = 1e6+5;
            ll fac[maxn];
int main(){
            int n;
            fac[0] = 1; 
            for(int i=1; i<maxn; i++) {
                fac[i] = fac[i-1] * i % mod;
            }
            while(~scanf("%d", &n)) {
                if(n >= mod) puts("0");
                else {
                    
                    printf("%lld\n", fac[n]);
                }
            }

            return 0;
}
View Code

1011

思路:主席樹找區間第$k$大

代碼:

#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 = 5e6 + 5;//M爲節點個數,爲Q*log(N)
int root[N], lson[M], rson[M], value[M], tot = 0;
int a[N], v[N];
vector<int>vc;
int n, m, l, r, k, q;
void build(int &x, int l, int r) {
    x = ++tot;
    if(l == r) {
        value[x] = 0;
        return ;
    }
    int m = (l+r) >> 1;
    build(lson[x], l, m);
    build(rson[x], m+1, r);
    value[x] = value[lson[x]] + value[rson[x]];
}
void update(int old, int &x, int p, int v, int l, int r) {
    x = ++tot;
    lson[x] = lson[old], rson[x] = rson[old], value[x] = value[old] + v;
    if(l == r) return ;
    int m = (l+r) >> 1;
    if(p <= m) update(lson[x], lson[x], p, v, l, m);
    else update(rson[x], rson[x], p, v, m+1, r);
}
int query(int x, int y, int l, int r, int k) {
    if(l == r) return l;
    int m = (l+r) >> 1, cnt = value[lson[y]] - value[lson[x]];
    if(k <= cnt) return query(lson[x], lson[y], l, m, k);
    else return query(rson[x], rson[y], m+1, r, k-cnt);
}
int main() {
    while(~scanf("%d %d", &n, &m)) {
        vc.clear();        
        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++) {
           int id = lower_bound(vc.begin(), vc.end(), a[i]) - vc.begin() + 1;
           v[id] = a[i];
           a[i] = id;
        }
        tot = 0;
        build(root[0], 1, n);
        for (int i = 1; i <= n; i++) update(root[i-1], root[i], a[i], 1, 1, n);
        while(m--) {
            scanf("%d %d", &l, &r);
            vector<int> t; 
            if(r-l+1 > 50) {
                int up = 45;
                for (int k = 1; k <= up; ++k) t.pb(v[query(root[l-1], root[r], 1, n, (r-l+1-k+1))]);
            }
            else {
                for (int k = l; k <= r; ++k) t.pb(v[a[k]]);
                sort(t.begin(), t.end(), greater<int>());
            }
            LL ans = -1;
            //cout << t.size() << endl;
            for (int i = 0; i+2 < t.size(); ++i) {
                if(t[i+1]+t[i+2] > t[i]) {
                    ans = 1LL*t[i]+1LL*t[i+1]+1LL*t[i+2];
                    break;
                }
            }
            printf("%lld\n", ans);
        }
    }
    return 0;
}
View Code

1012

思路:考慮到固定一個右端點,對於每種顏色,可行的區間是兩段區間(一段包含至少$k$個,一段一個都不包含),那麼咱們用線段樹維護這些區間,

最後找第一個被$c$種顏色覆蓋的位置。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 1e5 + 5;
int n, c, k, a[N];
vector<int> vc[N];
struct Node {
    int v, lz;
}tree[N<<2];
inline void push_up(int rt) {
    tree[rt].v = max(tree[rt<<1].v, tree[rt<<1|1].v);
}
inline void push_down(int rt) {
    tree[rt<<1].v += tree[rt].lz;
    tree[rt<<1].lz += tree[rt].lz;
    tree[rt<<1|1].v += tree[rt].lz;
    tree[rt<<1|1].lz += tree[rt].lz;
    tree[rt].lz = 0;
}
void build(int rt, int l, int r) {
    tree[rt].lz = 0;
    if(l == r) {
        tree[rt].v = c;
        return ;
    }
    int m = l+r >> 1;
    build(ls);
    build(rs);
    push_up(rt);
}
void update(int L, int R, int x, int rt, int l, int r) {
    if(L <= l && r <= R) {
        tree[rt].v += x;
        tree[rt].lz += x;
        return ;
    }
    if(tree[rt].lz) push_down(rt);
    int m = l+r >> 1;
    if(L <= m) update(L, R, x, ls);
    if(R > m) update(L, R, x, rs);
    push_up(rt);
}
int query(int x, int rt, int l, int r) {
    if(l == r) return l;
    int m = l+r >> 1;
    if(tree[rt].lz) push_down(rt);
    if(tree[rt<<1].v == x) return query(x, ls);
    else if(tree[rt<<1|1].v == x) return query(x, rs);
    else return -1;
}
int main() {
    while(~scanf("%d %d %d", &n, &c, &k)) {
        for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
        for (int i = 1; i <= c; ++i) vc[i].clear();
        build(1, 1, n); int ans = 0;
        for (int i = 1; i <= n; ++i) {
            vc[a[i]].pb(i);
            update(vc[a[i]].size() == 1?1:(vc[a[i]][vc[a[i]].size()-2]+1), vc[a[i]].back(), -1, 1, 1, n);
            if(vc[a[i]].size() >= k) update(vc[a[i]].size() == k?1:(vc[a[i]][vc[a[i]].size()-k-1]+1), vc[a[i]][vc[a[i]].size()-k], 1, 1, 1, n);
            int p = query(c, 1, 1, n);
            if(~p)ans = max(ans, i-p+1);
        }
        printf("%d\n", ans);
    }
    return 0;
}
View Code

 2019 Multi-University Training Contest 3

Solved Pro.ID Title
  1001 Azshara's deep sea
    1002 Blow up the city
  1003 Yukikaze and Demons
  1004 Distribution of books
  1005 Easy Math Problem
  1006 Fansblog
  1007 Find the answer
    1008 Game
  1009 K Subsequence
  1010 Sindar's Art Exhibition
  1011 Squrirrel

1001

1002

思路:建反向圖,而後就是求DAG的從入度爲0出發的支配樹。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 1e5 + 5;
vector<int> g[N], rg[N];
queue<int> q;
int in[N], T, Q, n, m, u, v, dp[N], anc[N][18];
inline int lca(int u, int v) {
    if(dp[u] < dp[v]) swap(u, v);
    for (int i = 17; i >= 0; --i) if(dp[anc[u][i]] >= dp[v]) u = anc[u][i];
    if(u == v) return u;
    for (int i = 17; i >= 0; --i) if(anc[u][i] != anc[v][i]) u = anc[u][i], v = anc[v][i];
    return anc[u][0];
}
int main() {
    scanf("%d", &T);
    while(T--) {
        scanf("%d %d", &n, &m);
        for (int i = 1; i <= m; ++i){
            scanf("%d %d", &u, &v);
            g[v].pb(u);
            in[u]++;
            rg[u].pb(v);
        }
        for (int i = 1; i <= n; ++i) if(!in[i]) q.push(i);
        while(!q.empty()) {
            int u = q.front();
            q.pop();
            int l;
            if(rg[u].size() == 0) l = 0;
            else {
                l = rg[u][0];
                for (int i = 1; i < rg[u].size(); ++i) {
                    int v = rg[u][i];
                    l = lca(l, v);
                }
            }
            anc[u][0] = l;
            for (int i = 1; i < 18; ++i) anc[u][i] = anc[anc[u][i-1]][i-1];
            dp[u] = dp[l]+1;
            for (int v : g[u]) {
                in[v]--;
                if(!in[v]) q.push(v);
            }
        }
        scanf("%d", &Q);
        while(Q--) {
            scanf("%d %d", &u, &v);
            printf("%d\n", dp[u]+dp[v]-dp[lca(u, v)]);
        }
        for (int i = 0; i <= n; ++i) g[i].clear(), rg[i].clear(), in[i] = 0;
    }
    return 0;
}
View Code

1003

1004

隊友補了

1005

1006

思路:首先要知道一個公式:$(p-1)!\%p = p-1$。這個公式好像叫威爾遜定理。而後由於素數之間的距離很近,咱們能夠暴力往前找那個素數$Q$,

只要先預處理$1e7$之內的素數就能夠了。最後把那個公式的階乘除到$Q!$,還有一點要注意$1e14$作乘法會爆,要用__int128或者快速乘。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 1e7 + 5;
LL MOD;
LL q_pow(__int128 n, __int128 k) {
    __int128 res = 1;
    while(k) {
        if(k&1) res = (res * n) % MOD;
        n = (n*n) % MOD;
        k >>= 1;
    }
    return (LL)res;
}
int prime[N], cnt;
bool not_p[N];
void init() {
    for (int i = 2; i < N; ++i) {
        if(!not_p[i]) prime[++cnt] = i;
        for (int j = 1; j <= cnt && i*prime[j] < N; ++j) {
            not_p[i*prime[j]] = true;
            if(i%prime[j] == 0) break;
        }
    }
}
int T;
int main() {
    init();
    scanf("%d", &T);
    while(T--) {
        scanf("%lld", &MOD);
        LL now;
        for (now = MOD-1; ; --now) {
            bool f = true;
            for (int j = 1; prime[j]*1LL*prime[j] <= now; ++j) {
                if(now%prime[j] == 0) {
                    f = false;
                    break;
                }
            }
            if(f) break;
        }
        __int128 ans = (MOD-1)%MOD;
        for (LL i = MOD-1; i > now; --i) ans = (ans * q_pow(i, MOD-2))%MOD;
        printf("%lld\n", (LL)ans);
    }
    return 0;
}
View Code

1007

思路:離散化+線段樹。對於每一個位置在前$i-1$個數中,找一個$k$使得前$k$大加起來大於等於$sum_i-m$。爲何一作到這種題就想到Splay。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 2e5 + 10;
int ch[N][2], val[N], cnt[N], fa[N], sz[N], lazy[N], ncnt = 0, rt = 0;
LL sum[N];
inline int ck(int x) {
    return ch[fa[x]][1] == x;
}
inline void push_up(int x) {
    sum[x] = sum[ch[x][0]] -val[x]*1LL*cnt[x] + sum[ch[x][1]];
    sz[x] = sz[ch[x][0]] + sz[ch[x][1]] + cnt[x];
}
void Rotate(int x) {
    int y = fa[x], z = fa[y];
    int k = ck(x), w = ch[x][k^1];
    ch[y][k] = w, fa[w] = y;
    ch[z][ck(y)] = x, fa[x] = z;
    ch[x][k^1] = y, fa[y] = x;
    push_up(y), push_up(x);
}
void Splay(int x, int goal = 0) {
    while(fa[x] != goal) {
        int y = fa[x], z = fa[y];
        if(z != goal) {
            if(ck(x) == ck(y)) Rotate(y);
            else Rotate(x);
        }
        Rotate(x);
    }
    if(!goal) rt = x;
}
void Find(int x) {
    if(!rt) return ;
    int cur = rt;
    while(ch[cur][x>val[cur]] && x != val[cur]) cur = ch[cur][x>val[cur]];
    Splay(cur);
}
void Insert(int x) {
    int cur = rt, p = 0;
    while(cur && val[cur] != x) {
        p = cur;
        cur = ch[cur][x>val[cur]];
    }
    if(cur) cnt[cur]++;
    else {
        cur = ++ncnt;
        if(p) ch[p][x>val[p]] = cur;
        fa[cur] = p;
        ch[cur][0] = ch[cur][1] = 0;
        val[cur] = x;
        sum[cur] = 0;
        cnt[cur] = sz[cur] = 1;
    }
    Splay(cur);
}
int get(LL k) {
    int cur = rt, now = 0;
    while(true) {
        if(ch[cur][0] && k <= sum[ch[cur][0]]) cur = ch[cur][0];
        else if(k > sum[ch[cur][0]] + abs(val[cur])*1LL*cnt[cur]) k -= sum[ch[cur][0]] + abs(val[cur])*1LL*cnt[cur], now += sz[ch[cur][0]]+cnt[cur], cur = ch[cur][1];
        else {
            int tmp = (k-sum[ch[cur][0]]+abs(val[cur])-1)/abs(val[cur]);
//            cout << tmp << endl;
            now += sz[ch[cur][0]]+tmp;
            return now;
        }
    }
}
inline void init() {
    ncnt = rt = ch[0][0] = ch[0][1] = fa[0] = sz[0] = cnt[0] = val[0] = sum[0] = 0;
}
int n, m, T, a[N];
//void Output(int x) {
//    if(ch[x][0]) Output(ch[x][0]);
//    printf("%d ", val[x]);
//    if(ch[x][1]) Output(ch[x][1]);
//}
int main() {
    scanf("%d", &T);
    while(T--) {
        init();
        scanf("%d %d", &n, &m);
        LL s = 0;
        for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
        for (int i = 1; i <= n; ++i) {
            s += a[i];
            if(s <= m)printf("0");
            else printf("%d", get(s-m));
            Insert(-a[i]);
            if(i == n) printf(" \n");
            else printf(" ");
        }
    }
    return 0;
}
View Code

1008

隊友補了

1009

思路:最小費用流。關於建圖有一個優化的地方,每一個位置和後面比他大元素鏈接時,這些比他大的元素構成遞減序列,這樣就能夠少連不少條邊,那麼要保證每一個位置能夠跑屢次,只有第一次纔有費用,能夠在某些點之間(自行考慮)多連一條容量無窮,費用爲0的邊。最後再加上Dijkstra的費用流板子,就能夠跑$78ms$了。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 4e3 + 10;
const int INF = 0x3f3f3f3f;
struct edge {
    int to, cap, cost, rev;
};
int V, a[N];
vector<edge>g[N];
int h[N], dis[N], prevv[N], preve[N];
void add_edge(int u, int v, int cap, int cost) {
    g[u].pb({v, cap, cost, g[v].size()});
    g[v].pb({u, 0, -cost, g[u].size()-1});
}
int min_cost_flow(int s, int t, int f) {
    int res = 0;
    mem(h, 0);
    while(f > 0) {
        priority_queue<pii, vector<pii>, greater<pii> > q;
        mem(dis, 0x3f);
        dis[s] = 0;
        q.push({0, s});
        while(!q.empty()) {
            pii p = q.top();
            q.pop();
            int v = p.se;
            if(dis[v] < p.fi) continue;
            for (int i = 0; i < g[v].size(); ++i) {
                edge &e = g[v][i];
                if(e.cap > 0 && dis[e.to] > dis[v] + e.cost + h[v] - h[e.to]) {
                    dis[e.to] = dis[v] + e.cost + h[v] - h[e.to];
                    prevv[e.to] = v;
                    preve[e.to] = i;
                    q.push({dis[e.to], e.to});
                }
            }
        }
        if(dis[t] == INF) return -1;
        for (int v = 0; v < V; ++v) h[v] += dis[v];
        int d = f;
        for (int v = t; v != s; v = prevv[v]) d = min(d, g[prevv[v]][preve[v]].cap);
        f -= d;
        res += d*h[t];
        for (int v = t; v != s; v = prevv[v]) {
            edge &e = g[prevv[v]][preve[v]];
            e.cap -= d;
            g[v][e.rev].cap += d;
        }
    }
    return res;
}
int main(){
            int T;  scanf("%d", &T);
            while(T--) {
                int n,k;
                scanf("%d%d", &n, &k);
                int s = 0, t = 2 * n + 1, ss = t+1;
                V = ss+1;
                for(int i=1; i<=n; i++) {
                    scanf("%d", &a[i]);
                    add_edge(i, i+n, 1, -1*a[i]);
                    add_edge(i, i+n, INF, 0);
                }
                for(int i=1; i<=n; i++) {
                    add_edge(s, i, 1, 0);
                    add_edge(i + n, t, 1, 0);
                    int now = INT_MAX;
                    for(int j=i+1; j<=n; j++) {
                        if(a[i] <= a[j] && a[j] < now) {
                            add_edge(i+n, j, INF, 0);
                            now = min(now, a[j]);
                        }
                    }
                }
                add_edge(ss, s, k, 0);
                printf("%lld\n", -min_cost_flow(ss, t, k));
                for (int i = 0;i < V; ++i) g[i].clear();
            }
            return 0;
}
View Code

1010

1011

隊友補了

2019 Multi-University Training Contest 4

Solved Pro.ID Title
  1001 AND Minimum Spanning Tree
  1002 Colored Tree
  1003 Divide the Stones
  1004 Enveloping Convex
  1005 Good Numbers
  1006 Horse
  1007 Just an Old Puzzle
  1008 K-th Closest Distance
  1009 Linear Functions
  1010 Minimal Power of Prime

1001

思路:若是$n==2^p-1$,那麼最小權值是1;不然最小權值是0。$f_i$爲最小的$2^p$使得$i\&{2}^{p} == 0$。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 2e5 + 5;
int T, n, p[21], ans[N];
int main() {
    p[0] = 1;
    for (int i = 1; i <= 20; ++i) p[i] = p[i-1]*2;
    scanf("%d", &T);
    while(T--) {
        scanf("%d", &n);
        int res = 0;
        bool f = true;
        for (int i = 1; i < 20; ++i) {
            if(n == p[i]-1) {
                f = false;
                break;
            }
        }
        if(f) res = 0;
        else res = 1;
        printf("%d\n", res);
        if(f) {
            for (int i = 2; i <= n; ++i) {
                if(i%2 == 0) ans[i] = 1;
                else {
                    int now = 0;
                    for (int j = 0; j <= 20; ++j) {
                        if(p[j] <= n && (p[j]&i) == 0) {
                            ans[i] = p[j];
                            break;
                        }
                    }
                }
            }
        }
        else {
            ans[n] = 1;
            for (int i = 2; i < n; ++i) {
                if(i%2 == 0) ans[i] = 1;
                else {
                    int now = 0;
                    for (int j = 0; j <= 20; ++j) {
                        if(p[j] <= n && (p[j]&i) == 0) {
                            ans[i] = p[j];
                            break;
                        }
                    }
                }
            }
        }
        for (int i = 2; i <= n; ++i) printf("%d%c", ans[i], " \n"[i==n]);
    }
    return 0;
}
View Code

1002

1003

思路:構造。打表找規律。

代碼:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+10;
vector<int> vs[maxn];
int main(){
    int T; scanf("%d",&T);
    while(T--){
        int n,k; scanf("%d %d",&n,&k);
        if(n==k){
            if(n==1) { printf("yes\n"); printf("1\n");}
            else     { printf("no\n"); }
            continue;
        }
        ll num=1ll*(1+n)*n/2;
        if(num%k!=0){
            printf("no\n");
            continue;
        }
        int x=n/k;int c=1;
        if(x%2==1){
            if(k%2==0){
                printf("no\n");
                continue;
            }
            for(int i=1;i<=x;i++){
                if(i==1){
                    for(int j=1;j<=k;j++) { vs[j].push_back(c); c++;}
                    for(int j=k;j>=1;j-=2) { vs[j].push_back(c); c++;  }
                    for(int j=k-1;j>=1;j-=2){ vs[j].push_back(c); c++; }
                    for(int j=k-1;j>=1;j-=2){vs[j].push_back(c); c++; }
                    for(int j=k;j>=1;j-=2) {vs[j].push_back(c); c++; }
                    i++; i++;
                }
                else {
                    for(int j=1;j<=k;j++) { vs[j].push_back(c); c++;}
                    for(int j=k;j>=1;j--) {vs[j].push_back(c); c++;}
                    i++;
                }
            }
        }
        else {
             for(int i=1;i<=x;i++){
                for(int j=1;j<=k;j++) { vs[j].push_back(c); c++;}
                for(int j=k;j>=1;j--) {vs[j].push_back(c); c++;}
                i++;
            }
        }
        printf("yes\n");
        for(int i=1;i<=k;i++){
            for(int j=0;j<vs[i].size();j++){
                if(j!=0) printf(" ");
                printf("%d",vs[i][j]);
            }
            printf("\n"); vs[i].clear();
        }
    }
}
View Code

1004

1005

1006

思路:斜率優化dp。維護遞增斜率$\frac{dp[j]-dp[k]+s[k]-s[j]+j*sum[j]-k*sum[k]}{sum[j]-sum[k]}$,其中$sum_i$表示前綴和,$s_i$表示前綴和的前綴和。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

const int N = 1e4 + 10;
int T, n, k, m, h[N];
vector<int> vc;
LL dp[N][55], sum[N], s[N];
deque<int> q[55];
inline LL up(int k, int j, int p) {
    return dp[j][p]-dp[k][p]+s[k]-s[j]+j*sum[j]-k*sum[k];
}
inline LL dw(int k, int j) {
    return sum[j]-sum[k];
}
inline bool g(int k, int j, LL c, int p) {
    return up(k, j, p) <= c*dw(k, j);
}
inline bool gg(int k, int j, int i, int p) {
    return up(k, j, p)*dw(j, i) >= up(j, i, p)*dw(k, j);
}
int main() {
    scanf("%d", &T);
    while(T--) {
        vc.clear();
        scanf("%d %d %d", &n, &k, &m);
        for (int i = 1; i <= n; ++i) scanf("%d", &h[i]), vc.pb(h[i]*(n-i+1)), sum[i] = sum[i-1]+h[i], s[i] = s[i-1]+sum[i];
        for (int i = 0; i <= n; ++i) for (int j = 0; j <= k+1; ++j) dp[i][j] = 1LL<<60;
        dp[0][0] = 0;
        sort(vc.begin(), vc.end(), greater<int>());
        LL ans = 0;
        for (int i = 0; i < m; ++i) ans += vc[i];
        for (int i = 0; i <= k+1; ++i) q[i].clear();
        q[0].push_back(0);
        for (int i = 1; i <= n; ++i) {
            for (int j = k; j >= 0; --j) {
                while(q[j].size() >= 2) {
                    int a = q[j].front();
                    q[j].pop_front();
                    int b = q[j].front();
                    if(g(a, b, i, j)) ;
                    else {
                        q[j].push_front(a);
                        break;
                    }
                }
                if(!q[j].empty()) {
                    int x = q[j].front();
                    dp[i][j+1] = dp[x][j]+s[i]-s[x]-(i-x)*sum[x];
                    while(q[j+1].size() >= 2) {
                        int b = q[j+1].back();
                        q[j+1].pop_back();
                        int a = q[j+1].back();
                        if(gg(a, b, i, j+1)) ;
                        else {
                            q[j+1].push_back(b);
                            break;
                        }
                    }
                    q[j+1].push_back(i);
                }
            }
        }
        LL tmp = 1LL<<60;
        for (int j = 1; j <= k+1; ++j) tmp = min(tmp, dp[n][j]);
        printf("%lld\n", ans-tmp);
    }
    return 0;
}
View Code

1007

思路:將0當作16,0每移動一個位置會改變奇數個逆序數,因此逆序數和移動距離奇偶性相同。

代碼:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_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 pli pair<LL, int>
#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 debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head

int T, n, a[10][10];
vector<int> vc;
int main() {
    scanf("%d", &T);
    while(T--) {
        vc.clear();
        int ans = 0, d = 0;
        for (int i = 1; i <= 4; ++i) for (int j = 1; j <= 4; ++j) {
            scanf("%d", &a[i][j]);
            if(a[i][j] == 0) a[i][j] = 16, d = (4-i)+(4-j);
            vc.pb(a[i][j]);
        }

        for (int i = 0; i < vc.size(); ++i) {
            for (int j = i+1; j< vc.size(); ++j) {
                if(vc[i] > vc[j]) ans++;
            }
        }
        if(ans%2 == d%2) printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}
View Code

1008

思路:先創建一顆劃分樹。而後對於每一個查詢咱們二分答案$mid$,那麼就是找$L$到$R$這段區間有多少個數值在區間$[p-mid, p+mid]$,這個能夠在劃分樹上每一個節點二分實現。

單次查詢複雜度$O(log(n)^3)$。

代碼:

相關文章
相關標籤/搜索