The 16th Zhejiang Provincial Collegiate Programming Contest Sponsored by TuSimple (Mirror)

B题

思路

因为
\[ x=\sum\limits_{k=1}^{n}ka_k\\ y=\sum\limits_{k=1}^{n}ka_{k}^{2} \]
我们设交换前和交换后的这两个等式的值设为\(x_1,y_1,x_2,y_2\),现在我们开始愉快的推公式
\[ \begin{aligned} &x_1-x_2=(i-j)(a_i-a_j)&\\ &y_1-y_2=(i-j)(a_i^2-a_j^2)&\\ \Rightarrow &\frac{y1-y2}{x_1-x_2}=a_i-a_j&(1)\\ &j=i-\frac{x_1-x_2}{a_i-a_j}&(2) \end{aligned} \]
然后我们枚举每一个\(i\),根据\((1)(2)\)计算出\(a_j\)\(j\)然后判断现在在\(j\)这个位置上的值是不是你算出来的这个\(a_j\),是就答案加一否则答案不变。

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

#define bug printf("********\n")
#define FIN freopen("in.txt","r",stdin)
#define debug(x) cout<<"["<<x<<"]"<<endl

typedef long long LL;
const int mod = 1e9 + 7;
const int maxn = 1e5 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;

int t, n;
LL x, y, b[maxn], cnt[maxn];

int main() {
#ifndef ONLINE_JUDGE
    FIN;
#endif // ONLINE_JUDGE
    scanf("%d", &t);
    while(t--) {
        scanf("%d%lld%lld", &n, &x, &y);
        LL xx = 0, yy = 0;
        for(int i = 1; i <= n; ++i) {
            scanf("%lld", &b[i]);
            cnt[b[i]]++;
            xx += b[i] * i;
            yy += b[i] * b[i] * i;
        }
        LL dx = xx - x, dy = yy - y;
        LL ans = 0;
        if(dx == 0 && dy == 0) {
            for(int i = 1; i <= n; ++i) {
                ans += cnt[b[i]] - 1;
                cnt[b[i]]--;
            }
            printf("%lld\n", ans);
            for(int i = 1; i <= n; ++i) cnt[b[i]] = 0;
            continue;
        }
        if(dx == 0 || dy == 0 || dy % dx) {
            printf("0\n");
            for(int i = 1; i <= n; ++i) cnt[b[i]] = 0;
            continue;
        }
        LL num = dy / dx;
        for(int i = 1; i <= n; ++i) {
            if(num - b[i] <= 0) continue;
            LL num1 = b[i], num2 = num - num1;
            if(num1 == num2 || dx % (num1 - num2) != 0) continue;
            LL pos = i - dx / (num1 - num2);
            if(pos >= 1 && pos < i && b[pos] == num2) ans++;
        }
        printf("%lld\n", ans);
        for(int i = 1; i <= n; ++i) cnt[b[i]] = 0;
    }
    return 0;
}

E题

思路

线段树,对于每个点它是否修改取决于在原序列是否有比它大的数或者比它大的数进行过操作。

代码实现如下

#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> piL;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;

#define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("in","r",stdin)
#define IO ios::sync_with_stdio(false),cin.tie(0)

const double eps = 1e-8;
const int mod = 1e9 + 7;
const int maxn = 1e5 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;

int t, n;
int a[maxn], num[maxn];
vector<int> v;

struct node {
    int l, r, sum;
}segtree[maxn<<2];

int getid(int x) {
    return lower_bound(v.begin(), v.end(), x) - v.begin() + 1;
}

void push_up(int rt) {
    segtree[rt].sum = segtree[lson].sum + segtree[rson].sum;
}

void build(int rt, int l, int r) {
    segtree[rt].l = l, segtree[rt].r = r;
    segtree[rt].sum = 0;
    if(l == r) return;
    int mid = (l + r) >> 1;
    build(lson, l, mid);
    build(rson, mid + 1, r);
}

void update(int rt, int pos) {
    if(segtree[rt].l == segtree[rt].r) {
        segtree[rt].sum++;
        return;
    }
    int mid = (segtree[rt].l + segtree[rt].r) >> 1;
    if(pos <= mid) update(lson, pos);
    else update(rson, pos);
    push_up(rt);
}

int query(int rt, int l, int r) {
    if(segtree[rt].l == l && segtree[rt].r == r) {
        return segtree[rt].sum;
    }
    int mid = (segtree[rt].l + segtree[rt].r) >> 1;
    if(r <= mid) return query(lson, l, r);
    else if(l > mid) return query(rson, l, r);
    else return query(lson, l, mid) + query(rson, mid + 1, r);
}

int main() {
    scanf("%d", &t);
    while(t--) {
        scanf("%d", &n);
        v.clear();
        priority_queue<pii> q;
        for(int i = 1; i <= n; ++i) {
            scanf("%d", &a[i]);
            num[i] = 0;
            v.push_back(a[i]);
            q.push({a[i], i});
        }
        sort(v.begin(), v.end());
        v.erase(unique(v.begin(), v.end()), v.end());
        build(1, 1, v.size() + 1);
        for(int i = 1; i <= n; ++i) {
            num[i] = query(1, getid(a[i]) + 1, v.size() + 1);
            update(1, getid(a[i]));
        }
        int x;
        int ans = 0, las = 0;
        build(1, 1, v.size() + 1);
        while(!q.empty()) {
            int x = q.top().second; q.pop();
            if(num[x] || query(1, getid(a[x]) + 1, v.size() + 1)) {
                ans++;
                update(1, getid(a[x]));
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}

F题

思路

暴力模拟即可。

代码实现如下

#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> piL;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;

#define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("in","r",stdin)
#define IO ios::sync_with_stdio(false),cin.tie(0)

const double eps = 1e-8;
const int mod = 1e9 + 7;
const int maxn = 1e5 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;

int t;
vector<char> v;
char s[105];
set<char> st;

int main() {
    scanf("%d", &t);
    st.insert({'a', 'e', 'i', 'y', 'o', 'u'});
    while(t--) {
        scanf("%s", s);
        v.clear();
        int len = strlen(s), flag = 0;
        for(int i = 0; i < len; ++i) {
            if(!st.count(s[i])) v.push_back(s[i]), flag = 1;
            else if(!flag) v.push_back(s[i]), flag = 1;
        }
        for(int i = 0; i < (int)v.size(); ++i) {
            printf("%c", v[i]);
        }
        printf("\n");
    }
    return 0;
}

G题

思路

暴力判断。

代码实现如下

#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> piL;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;

#define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("in","r",stdin)
#define IO ios::sync_with_stdio(false),cin.tie(0)

const double eps = 1e-8;
const int mod = 1e9 + 7;
const int maxn = 1e5 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;

int t, n;

bool check(int x) {
    return x % 7 == 0 && x % 4 != 0;
}

int main() {
    scanf("%d", &t);
    while(t--) {
        scanf("%d", &n);
        while(!check(n)) n++;
        printf("%d\n", n);
    }
    return 0;
}

H题

思路实现如下

暴力枚举每个点删除会对答案的影响,然后对所有情况取最小值。

代码实现如下

#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> piL;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;

#define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("in","r",stdin)
#define IO ios::sync_with_stdio(false),cin.tie(0)

const double eps = 1e-8;
const int mod = 1e9 + 7;
const int maxn = 1e5 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;

int t, n;
int a[maxn];

int main() {
    scanf("%d", &t);
    while(t--) {
        scanf("%d", &n);
        for(int i = 0; i <= n + 1; ++i) {
            a[i] = inf;
        }
        for(int i = 1; i <= n; ++i) {
            scanf("%d", &a[i]);
        }
        int sum = 0;
        for(int i = 2; i < n; ++i) {
            if(a[i] > a[i-1] && a[i] > a[i+1]) {
                sum++;
            }
        }
        int ans = sum;
        for(int i = 1; i <= n; ++i) {
            int num = 0;
            if(a[i] > a[i-1] && a[i] > a[i+1]) {
                num++;
                if(i >= 2 && a[i-1] > a[i-2] && a[i-1] > a[i+1]) num--;
                if(i <= n - 2 && a[i+1] > a[i+2] && a[i+1] > a[i-1]) num--;
            } else {
                if(i >= 2) {
                    if(a[i-1] > a[i-2] && a[i-1] > a[i]) num++;
                    if(a[i-1] > a[i-2] && a[i-1] > a[i+1]) num--;
                }
                if(i <= n - 2) {
                    if(a[i+1] > a[i] && a[i+1] > a[i+2]) num++;
                    if(a[i+1] > a[i+2] && a[i+1] > a[i-1]) num--;
                }
            }
            ans = min(ans, sum - num);
        }
        printf("%d\n", ans);
    }
    return 0;
}

I题

思路

\(4\)的倍数往上每四个数异或后都会是\(0\),因此对\(a\)\(b\)枚举到在\([a,b]\)间离它们最近的\(4\)的倍数,然后把这中间的数进行异或即可。

代码实现如下

import java.util.*;
import java.math.*;

public class Main {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int t = sc.nextInt();
        while(t-- != 0) {
            BigInteger a = sc.nextBigInteger();
            BigInteger b = sc.nextBigInteger();
            int ans = 0;
            while(!a.mod(BigInteger.valueOf(3)).equals(BigInteger.ZERO) && a.compareTo(b) <= 0) {
                ans++;
                a = a.add(BigInteger.ONE);
            }
            while(!b.mod(BigInteger.valueOf(3)).equals(BigInteger.ZERO) && b.compareTo(a) > 0) {
                ans++;
                b = b.subtract(BigInteger.ONE);
            }
            System.out.println(ans % 2);
        }
        sc.close();
    }
}
T = eval(input())
while(T):
    T -= 1
    a, b = map(int, input().split())
    ans = 0
    while(a % 3 != 0 and a <= b):
        ans += 1
        a += 1
    while(b % 3 != 0 and b > a):
        ans += 1
        b -= 1
    print(ans % 2)

J题

思路

我们先用并查集来维护联通块,为了保持字典序最小,我们从小到大将每个联通块取一个数放进优先队列,然后跑\(bfs\)即可。

代码实现如下

#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> piL;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;

#define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("in","r",stdin)
#define IO ios::sync_with_stdio(false),cin.tie(0)

const double eps = 1e-8;
const int mod = 1e9 + 7;
const int maxn = 1e6 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;

int t, n, m, x, y;
vector<int> G[maxn];
priority_queue<int> q;
int fa[maxn], vis[maxn], pp[maxn];

int fi(int x) {
    return fa[x] == x ? x : fa[x] = fi(fa[x]);
}

void mer(int x, int y) {
    int p1 = fi(x), p2 = fi(y);
    if(p1 == p2) return;
    if(p1 < p2) {
        fa[p2] = p1;
    } else {
        fa[p1] = p2;
    }
}

int main() {
#ifndef ONLINE_JUDGE
    FIN;
#endif
    scanf("%d", &t);
    while(t--) {
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; ++i) {
            fa[i] = i;
            pp[i] = vis[i] = 0;
            G[i].clear();
        }
        for(int i = 1; i <= m; ++i) {
            scanf("%d%d", &x, &y);
            G[x].push_back(y);
            G[y].push_back(x);
            mer(x, y);
        }
        while(!q.empty()) q.pop();
        for(int i = 1; i <= n; ++i) {
            int p = fi(i);
            if(pp[p]) continue;
            q.push(-p);
            pp[p] = 1;
        }
        printf("%d\n", (int)q.size());
        int flag = 0;
        while(!q.empty()) {
            int u = -q.top(); q.pop();
            if(vis[u]) continue;
            if(flag) printf(" ");
            flag = 1;
            printf("%d", u);
            vis[u] = 1;
            for(int i = 0; i < (int)G[u].size(); ++i) {
                int v = G[u][i];
                if(vis[v]) continue;
                q.push(-v);
            }
        }
        printf("\n");
    }
    return 0;
}

K题

思路

这题我们分两种情况进行分析:
\(1.s==t:\)这种情况我们可以用\(manacher\)\(s\)中的所有回文子串数计算出来;
\(2.s!=t:\)这种情况我们先找到\(s\)中与\(t\)不相同的最左最右的端点,然后判断这一段能否翻转使得\(s==t\),不能答案就是\(0\),否则就枚举这个区间能够向外延伸多远。

代码实现如下

#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> piL;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;

#define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("in.txt","r",stdin)
#define IO ios::sync_with_stdio(false),cin.tie(0)

const double eps = 1e-8;
const int mod = 1e9 + 7;
const int maxn = 1e5 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;

int t, n;
LL x, y, xx, yy, b[maxn];
map<LL, int> cnt;

int main() {
#ifndef ONLINE_JUDGE
    FIN;
#endif
    scanf("%d", &t);
    while(t--) {
        scanf("%d%lld%lld", &n, &x, &y);
        xx = yy = 0;
        cnt.clear();
        for(int i = 1; i <= n; ++i) {
            scanf("%lld", &b[i]);
            xx += b[i] * i;
            yy += b[i] * b[i] * i;
            cnt[b[i]]++;
        }
        LL ans = 0;
        if(x != xx) {
            if((y - yy) % (x - xx) != 0) {
                printf("0\n");
                continue;
            }
            LL num = (y - yy) / (x - xx);
            for(int i = 1; i <= n; ++i) {
                LL num1 = b[i], num2 = num - b[i];
                if(num1 == num2) continue;
                LL tmp = num1 - num2;
                if((x - xx) % tmp != 0) continue;
                LL j = (x - xx) / tmp;
                LL pos = i + j;
                if(pos >= 1 && pos <= n && b[pos] == num2) ans++;
            }
            printf("%lld\n", ans/2);
        } else {
            if(y == yy) {
                for(int i = 1; i <= n; ++i) {
                    ans += cnt[b[i]] - 1;
                    cnt[b[i]]--;
                }
            }
            printf("%lld\n", ans);
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Dillonh/p/11162377.html