• 2019 Multi-University Training Contest 5


    Solved Pro.ID Title Ratio(Accepted / Submitted)
    1001 fraction 4.17%(7/168)
    已补 1002 three arrays 12.69%(76/599) 字典树
    1003 geometric problem 1.59%(1/63)
    已补 1004 equation 20.65%(310/1501) 思维
    已补 1005 permutation 1 24.77%(407/1643) dfs+思维
    img 1006 string matching 23.12%(724/3131) exkmp
    img 1007 permutation 2 47.19%(688/1458) DP
    img 1008 line symmetric 1.87%(11/588) 计算几何
    1009 discrete logarithm problem 18.42%(7/38)
    1010 find hidden array 6.25%(2/32)

    题目

    1002

    将a序列和b序列存放到两个字典树里面,然后每次贪心的匹配a中的0和b中0,或者a中的1和b中的1,如果没有,那就01或者10。最后获得的数字不一定是当前最小的,不过一定是在C中的,所以只需要在最后排个序就行了。

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 100010;
    int son[31*N][2],cnt[62*N],tot,n,x;
    vector<int> res;
    inline void insert(int head,int x){
        int p = head;
        for(int i=30;i>=0;i--){
            int u = x >> i & 1;
            if(!son[p][u])son[p][u] = ++tot;
            p = son[p][u];
            cnt[p]++;
        }
    }
    inline int getVal(int p1,int p2){
        int res = 0;
        for(int i=30;i>=0;i--){
            if(son[p1][0] && son[p2][0] && cnt[son[p1][0]] && cnt[son[p2][0]]){
                p1 = son[p1][0];
                p2 = son[p2][0];
                cnt[p1]--;cnt[p2]--;
            }
            else if(son[p1][1] && son[p2][1] && cnt[son[p1][1]] && cnt[son[p2][1]]){
                p1 = son[p1][1];
                p2 = son[p2][1];
                cnt[p1]--;cnt[p2]--;
            }
            else if(son[p1][1] && son[p2][0] && cnt[son[p1][1]] && cnt[son[p2][0]]){
                p1 = son[p1][1];
                p2 = son[p2][0];
                cnt[p1]--;cnt[p2]--;
                res |= (1<<i);
            }
            else if(son[p1][0] && son[p2][1] && cnt[son[p1][0]] && cnt[son[p2][1]]){
                p1 = son[p1][0];
                p2 = son[p2][1];
                cnt[p1]--;cnt[p2]--;
                res |= (1<<i);
            }
        }
        return res;
        
    }
    int main(){
        int T;scanf("%d",&T);
        while(T--){
            tot = 1;
            res.clear();
            scanf("%d",&n);
            for(int i=1;i<=n;i++){
                scanf("%d",&x);
                insert(0,x);
            }
            for(int i=1;i<=n;i++){
                scanf("%d",&x);
                insert(1,x);
            }
            for(int i=1;i<=n;i++)res.push_back(getVal(0,1));
            sort(res.begin(),res.end());
            for(int i=0;i<n;i++){
                if(i)printf(" ");
                printf("%d",res[i]);
            }
            puts("");
            for(int i=0;i<=tot;i++){
                son[i][0] = son[i][1] = 0;
                cnt[i] = 0;
            }
        }
        return 0;
    }
    

    1004

    把n个等式按照 (-bover a) 从小到大排序,然后可以发现把n条线(x={-bover a})画到坐标轴上面可以把x分为n+1个区域,针对每个区域,可以将每个等式的绝对值去掉,然后加到一起变成一个等式,直接解出来看x在不在这个范围即可

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll N = 100010;
    ll n;
    int t;
    ll C;
    ll gcd(ll a,ll b){
        return b == 0 ? a : gcd(b,a%b);
    }
    struct node{
        int a,b;
        bool operator <(const node y){
            return (-b) * y.a < -y.b * a;
        }
    }a[N];
    ll aa[N],bb[N],tot;
    int main(){
        scanf("%d",&t);
        while(t--){
            tot = 0;
            scanf("%lld%lld",&n,&C);
            ll A = 0,B = 0;
            for(ll i=1;i<=n;i++){
                scanf("%lld%lld",&a[i].a,&a[i].b);
                A += a[i].a;
                B += a[i].b;
            }
            sort(a+1,a+n+1);
            ll resa = 0, resb = 0;
            bool flag = false;
            for(ll i=n;i>=0;i--){
                if(A == 0){
                    if(B == C){
                        flag = true;
                        break;
                    }
                    else {
                        continue;
                    }
                }
                resa = C-B;
                resb = A;
                if(resb < 0){
                    resa = - resa;
                    resb = - resb;
                }
                ll g = gcd(resa > 0 ? resa : -resa,resb);
                if(g > 1){
                    resa/=g;
                    resb/=g;
                }
                if(i >= 1){
                    A -= 2 * a[i].a;
                    B -= 2 * a[i].b;
                }
                if(i >= 1 && resa * a[i].a < (-a[i].b * resb))continue;
                if(i < n && resa * a[i+1].a >= (-a[i+1].b * resb))continue;
                aa[++tot] = resa;
                bb[tot] = resb;
            }
            if(flag)puts("-1");
            else{
                printf("%lld",tot);
                for(ll i = tot; i>= 1;i--){
                    printf(" %lld/%lld",aa[i],bb[i]);
                }
                puts("");
            }
        }
        return 0;
    }
    

    1005

    企图用组合数学,一直wa找不着北,场后先找到前两个数字然后再dfs还是wa,看题解明白了,但是并不知道自己错在哪里

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 50;
    int n,k;
    int d[N],u[N];
    //d中存在n个数字,他们表示着相对大小,实际大小由整个数组的low和hi决定。
    //low表示现在填过的数字中最大的和最小的数字是多少。
    int dfs(int x,int low,int hi){
        if(x == n){
            k --;
            if(k == 0){
                for(int i=0;i<n;i++){
                    if(i)printf(" ");
                    printf("%d",d[i] - low + 1);
                }
                puts("");
                return 1;
            }
            return 0;
        }
        for(int i = hi - n + 1;i <= low + n -1;i++){
            if(u[i])continue;
            u[i] = 1;
            d[x] = i;
            if(dfs(x+1,min(low,i),max(hi,i)) == 1){
                u[i] = 0;
                return 1;
            }
            u[i] = 0;
        }
        return 0;
    }
    int main(){
        int T;scanf("%d",&T);
        while(T--){
            scanf("%d%d",&n,&k);
            d[0] = n;
            u[n] = 1;
            dfs(1,n,n);
            u[n] = 0;
        }
        return 0;
    }
    

    1006

    开场SA+LCP获得一T(看SA看晕了),回过头来发现就是个exkmp,直接上板子

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 1e6+10;
    char s[N];
    int nxt[N];
    void pre_EKMP(char x[],int m){
        nxt[0] = m;
        int j = 0;
        while(j+1 < m && x[j] == x[j+1])j++;
        nxt[1] = j;
        int k = 1;
        for(int i=2;i<m;i++){
            int p = nxt[k] + k - 1;
            int l = nxt[i-k];
            if(i + l < p + 1)nxt[i] = l;
            else{
                j = max(0,p-i+1);
                while(i + j < m && x[i+j] == x[j])j++;
                nxt[i] = j;
                k = i;
            }
        }
    }
    int main(){
        int T;scanf("%d",&T);
        while(T--){
            scanf("%s",s);
            int len = strlen(s);
            pre_EKMP(s,len);
            ll res = 0;
            for(int i=1;i<len;i++){
                if(nxt[i] == len - i){
                    res += nxt[i];
                }
                else res += nxt[i] + 1;
            }
            printf("%lld
    ",res);
        }
        return 0;
    }
    

    1007

    学长过的,是我不会的DP

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll mod = 998244353;
    
    ll dp[100005][2];
    int main() {
        dp[3][0] = 1LL;
        dp[3][1] = 0LL;
        dp[4][0] = 1LL;
        dp[4][1] = 1LL;
        for(int i = 5; i <= 100000; i++) {
            dp[i][0] = (dp[i - 1][0] + dp[i - 1][1]) % mod;
            dp[i][1] = dp[i - 2][0];
        }
    
        int T;
        scanf("%d", &T);
        while(T--) {
            int n, x, y;
            scanf("%d%d%d", &n, &x, &y);
            if(x + 1 == y && n > 3) {
                if(y == n || x == 1) puts("1");
                else puts("0");
                continue;
            }
            ll ans = 0;
            int l, r;
            if(x == 1) l = 1;
            else l = x + 1;
            if(y == n) r = n;
            else r = y - 1;
            r -= l - 1;
            //cout << r << endl;
            if(r <= 3) ans = 1LL;
            else ans = (dp[r][0] + dp[r][1]) % mod;
    
            printf("%lld
    ", ans);
        }
        return 0;
    }
    

    1008

    学长过的,我什么都不会

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const double eps = 1e-8;
    int cmp(double x) {
        if (fabs(x) < eps) return 0;
        if (x > 0) return 1;
        return -1;
    }
    
    const double pi = acos(-1.0);
    
    inline double sqr(double x) {
        return x * x;
    }
    
    struct point {
        double x, y;
        point() {}
        point(double a, double b) : x(a), y(b) {}
        void input() {
            scanf("%lf%lf", &x, &y);
        }
        friend point operator + (const point &a, const point &b) {
            return point(a.x + b.x, a.y + b.y);
        }
        friend point operator - (const point &a, const point &b) {
            return point(a.x - b.x, a.y - b.y);
        }
        friend bool operator == (const point &a, const point &b) {
            return cmp(a.x - b.x) == 0 && cmp(a.y - b.y) == 0;
        }
        friend point operator * (const point &a, const double &b) {
            return point(a.x * b, a.y * b);
        }
        friend point operator * (const double &a, const point &b) {
            return point(a * b.x, a * b.y);
        }
        friend point operator / (const point &a, const double &b) {
            return point(a.x / b, a.y / b);
        }
        double norm(){
            return sqrt(sqr(x) + sqr(y));
        }
    };
    
    double det(const point &a, const point &b) {
        return a.x * b.y - a.y * b.x;
    }
    
    double dot(const point &a, const point &b) {
        return a.x * b.x + a.y * b.y;
    }
    
    double dist(const point &a, const point &b) {
        return  (a - b).norm();
    }
    
    point rotate_point(const point &p, double A){
        double tx = p.x, ty = p.y;
        return point(tx * cos(A) - ty * sin(A), tx * sin(A) + ty * cos(A));
    }
    
    struct line {
        point a, b;
        line() {}
        line(point x, point y) : a(x), b(y) {}
    };
    
    line point_make_line(const point a, const point b) {
        return line(a, b);
    }
    
    double dis_point_segment(const point p, const point s, const point t) {
        if(cmp(dot(p - s, t - s)) < 0) return (p - s).norm();
        if(cmp(dot(p - t, s - t)) < 0) return (p - t).norm();
        return fabs(det(s - p, t - p) / dist(s, t));
    }
    
    void PointProjLine(const point p, const point s, const point t, point &cp){
        double r = dot((t - s), (p - s)) / dot(t - s, t - s);
        cp = s + r * (t - s);
    }
    
    bool PointOnSegment(point p, point s, point t){
        return cmp(det(p - s, t - s)) == 0 && cmp(dot(p - s, p - t)) <= 0;
    }
    
    bool parallel(line a, line b){
        return !cmp(det(a.a - a.b, b.a - b.b));
    }
    
    bool line_make_point(line a, line b, point &res){
        if(parallel(a, b)) return false;
        double s1 = det(a.a - b.a, b.b - b.a);
        double s2 = det(a.b - b.a, b.b - b.a);
        res = (s1 * a.b - s2 * a.a) / (s1 - s2);
        return true;
    }
    
    line move_d(line a, const double &len){
        point d = a.b - a.a;
        d = d / d.norm();
        d = rotate_point(d, pi / 2);
        return line(a.a + d * len, a.b + d * len);
    }
    
    bool SegmentSamePoints(line i, line j){
        return max(i.a.x, i.b.x) >= min(j.a.x, j.b.x) &&
            max(j.a.x, j.b.x) >= min(i.a.x, i.b.x) &&
            max(i.a.y, i.b.y) >= min(j.a.y, j.b.y) &&
            max(j.a.y, j.b.y) >= min(i.a.y, i.b.y) &&
            cmp(det(j.a - i.a, i.b - i.a) * det(j.b - i.a, i.b - i.a)) <= 0 &&
            cmp(det(i.a - j.a, j.b - j.a) * det(i.b - j.a, j.b - j.a)) <= 0;
    }
    
    int T;
    
    int n;
    point a[1005];
    
    int main(){
        scanf("%d", &T);
        while(T--){
            scanf("%d", &n);
            for(int i = 0; i < n; i++){
                a[i].input();
            }
            if(n < 5){
                puts("Y");
                continue;
            }
    
            bool ans = false;
    
            // 关于某条边的中垂线对称
            for(int i = 0; i < n; i++){
                point fir = a[i];
                point sec = a[(i + 1) % n];
                point mid_p = (fir + sec) / 2;
    
                point ss1 = sec - fir;
                point mid_q = rotate_point(ss1, pi / 2) * (2500.0) + mid_p;
                point mid_r = rotate_point(ss1, -pi / 2) * (2500.0) + mid_p;
                
                int cnt = 0;
                for(int j = 1; j <= (n + 1) / 2 - 1; j++){
                    fir = a[(i + 1 + j) % n];
                    sec = a[(i - j + n) % n];
    
                    if(!(fir == sec) && cmp(dis_point_segment(fir, mid_q, mid_r)) == 0 && cmp(dis_point_segment(sec, mid_q, mid_r)) == 0){
                        cnt = 20;
                        break;
                    }
    
    
                    point mid_c = (fir + sec) / 2;
                    if(cmp(dis_point_segment(mid_c, mid_q, mid_r)) != 0){
                        cnt++;
                    }
    
                    point cp1, cp2;
                    PointProjLine(fir, mid_q, mid_r, cp1);
                    PointProjLine(sec, mid_q, mid_r, cp2);
                    if(!(cp1 == cp2)){
                        cnt++;
                    }
    
                    if(n % 2 == 0 && j == (n + 1) / 2 - 1){
                        point ss1 = a[(i + j) % n] - mid_q;
                        point ss2 = a[(i + j + 1) % n] - mid_q;
                        point ss3 = a[(i + j + 2) % n] - mid_q;
                        point ss4 = a[(i + j + 3) % n] - mid_q;
    
                        point ss5 = mid_r - mid_q;
    
                        int bb1 = cmp(det(ss5, ss2));
                        int bb2 = cmp(det(ss5, ss1));
                        int bb3 = cmp(det(ss5, ss3));
                        int bb4 = cmp(det(ss5, ss4));
    
                        int bb5 = bb1 * bb2;
                        int bb6 = bb4 * bb3;
    
                        if(bb5 > 0 || bb6 > 0){
                            ;
                        }
                        else{
                            cnt += 20;
                        }
                    }
    
                    if(cnt > 1){
                        break;
                    }
                }
    
                if(cnt <= 1){
                    ans = true;
                    break;
                }
            }
    
            if(ans){
                puts("Y");
                continue;
            }
    
            // 偶数点时:关于对边连线对称
            if(n % 2 == 0){
                for(int i = 0; i < n / 2; i++){
                    point fir = a[i];
                    point sec = a[i + n / 2];
    
                    point ss1 = sec - fir;
                    point mid_q = ss1 * 2500.0 + fir;
                    point mid_r = ss1 * (-2500.0) + fir;
    
                    int cnt = 0;
                    for(int j = 1; j < n / 2; j++){
                        fir = a[(i + j) % n];
                        sec = a[(i - j + n) % n];
    
                        if(!(fir == sec) && cmp(dis_point_segment(fir, mid_q, mid_r)) == 0 && cmp(dis_point_segment(sec, mid_q, mid_r)) == 0){
                            cnt = 20;
                            break;
                        }
    
                        point mid_c = (fir + sec) / 2;
                        if(cmp(dis_point_segment(mid_c, mid_q, mid_r)) != 0){
                            cnt++;
                            continue;
                        }
    
                        point cp1, cp2;
                        PointProjLine(fir, mid_q, mid_r, cp1);
                        PointProjLine(sec, mid_q, mid_r, cp2);
                        if(!(cp1 == cp2)){
                            cnt++;
                        }
    
                        if(cnt > 1){
                            break;
                        }
                    }
    
                    if(cnt <= 1){
                        ans = true;
                        break;
                    }
                }
                if(ans){
                    puts("Y");
                    continue;
                }
            }
            // 奇数点时:检查能不能调整正对的两个点。
            else{
                for(int i = 0; i < n; i++){
                    point fir = a[(i + 1) % n];
                    point sec = a[(i - 1 + n) % n];
    
                    point mid_p = (fir + sec) / 2;
    
                    point ss1 = mid_p - a[i];
                    point mid_q = ss1 * 2500.0 + a[i];
                    point mid_r = ss1 * (-2500.0) + a[i];
    
                    int cnt = 0;
                    for(int j = 1; j <= n / 2; j++){
                        // printf("%d
    ", j);
                        fir = a[(i + j) % n];
                        sec = a[(i - j + n) % n];
    
                    if(!(fir == sec) && cmp(dis_point_segment(fir, mid_q, mid_r)) == 0 && cmp(dis_point_segment(sec, mid_q, mid_r)) == 0){
                        cnt = 20;
                        break;
                    }
    
                        point mid_c = (fir + sec) / 2;
                        if(cmp(dis_point_segment(mid_c, mid_q, mid_r)) != 0){
                            // printf("%d: mid wrong
    ", j);
                            cnt++;
                        }
    
                        point cp1, cp2;
                        PointProjLine(fir, mid_q, mid_r, cp1);
                        PointProjLine(sec, mid_q, mid_r, cp2);
                        if(!(cp1 == cp2)){
                            // printf("%d: cp wrong
    ", j);
                            cnt++;
                        }
    
                        point ss1 = a[(i + j - 1 + n) % n] - mid_q;
                        point ss2 = a[(i + j) % n] - mid_q;
                        point ss3 = a[(i + j + 1) % n] - mid_q;
                        point ss4 = a[(i + j + 2) % n] - mid_q;
    
                        point ss5 = mid_r - mid_q;
    
                        int bb1 = cmp(det(ss5, ss2));
                        int bb2 = cmp(det(ss5, ss1));
                        int bb3 = cmp(det(ss5, ss3));
                        int bb4 = cmp(det(ss5, ss4));
    
                        int bb5 = bb1 * bb2;
                        int bb6 = bb4 * bb3;
    
                        if(bb5 > 0 || bb6 > 0){
                            ;
                        }
                        else{
                            cnt += 20;
                        }
    
                        if(cnt > 1){
                            break;
                        }
                    }
    
                    if(cnt <= 1){
                        // printf("%d
    ", i);
                        ans = true;
                        break;
                    }
                }
                if(ans){
                    puts("Y");
                    continue;
                }
            }
    
            // 偶数时:还要检查是不是正对面的点是偏的
            if(n % 2 == 0){
                for(int i = 0; i < n; i++){
                    point fir = a[(i + 1) % n];
                    point sec = a[(i - 1 + n) % n];
    
                    point mid_p = (fir + sec) / 2;
    
                    point ss1 = mid_p - a[i];
                    point mid_q = ss1 * 2500.0 + a[i];
                    point mid_r = ss1 * (-2500.0) + a[i];
    
                    int cnt = 0;
                    for(int j = 1; j <= n / 2; j++){
                        fir = a[(i + j) % n];
                        sec = a[(i - j + n) % n];
    
                        if(!(fir == sec) && cmp(dis_point_segment(fir, mid_q, mid_r)) == 0 && cmp(dis_point_segment(sec, mid_q, mid_r)) == 0){
                            cnt = 20;
                            break;
                        }
    
                        point mid_c = (fir + sec) / 2;
                        if(cmp(dis_point_segment(mid_c, mid_q, mid_r)) != 0){
                            cnt++;
                            continue;
                        }
    
                        point cp1, cp2;
                        PointProjLine(fir, mid_q, mid_r, cp1);
                        PointProjLine(sec, mid_q, mid_r, cp2);
                        if(!(cp1 == cp2)){
                            cnt++;
                        }
    
                        if(cnt > 1){
                            break;
                        }
                    }
    
                    if(cnt <= 1){
                        ans = true;
                        break;
                    }
                }
                if(ans){
                    puts("Y");
                    continue;
                }
            }
    
            if(ans){
                puts("Y");
            }
            else{
                puts("N");
            }
        }
        return 0;
    }
    
  • 相关阅读:
    Java代码是怎么运行的
    Java单例模式
    redis分布式锁实现
    zuul2.0
    配置ssh免密钥登陆多台从机
    Nifi-install-config
    Configure Access to Multiple Clusters
    kubernetes集群搭建(kubeadm,kubelet)
    shell 编程
    系统管理
  • 原文地址:https://www.cnblogs.com/1625--H/p/11305662.html
Copyright © 2020-2023  润新知