• 暑假最后一测


    题解:

    第一题:裸的exgcd,注意有很多特判;

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    const ll P = 65535;
    ll exgcd(ll a, ll b, ll &x, ll &y){
        if(!b){
            x = 1; y = 0; return a;
        }
        ll x0, y0;
        ll d = exgcd(b, a%b, x0, y0);
        x = y0;
        y = x0 - (a/b) * y0;
        return d;
    }
    int main(){
    //    freopen("fuction.in","r",stdin);
    //    freopen("fuction.out","w",stdout);
        int T;
        scanf("%d", &T);
        while(T--){
            ll a, b, c;
            scanf("%I64d%I64d%I64d", &a, &b, &c);
            if((!a && !b && c)){puts("0");continue;}
            if((!a && !b && !c)){puts("ZenMeZheMeDuo");continue;}
            if(!a || !b){
                if((!a && c * b > 0 && c%b == 0) || (!b && a * c > 0 && c%a == 0))puts("ZenMeZheMeDuo");
                else puts("0");
                continue;
            }
            
            ll x, y;
            ll d = exgcd(a, b, x, y);
            if(c % d){puts("0");continue;}
            x *= c/d;
            y *= c/d;
            if((a > 0 && b < 0) || (a < 0 && b > 0)){puts("ZenMeZheMeDuo");continue;}        
            
            ll deltax = b/d, deltay = a/d;
            deltax = abs(deltax), deltay = abs(deltay);
            
            ll x1 = (x % deltax + deltax) % deltax;
            if(!x1) x1 += deltax;
            ll y2 = (c - x1 * a) / b;
            
            ll yy1 = (y % deltay + deltay) % deltay;
            if(!yy1) yy1 += deltay;
            ll x2 = (c - yy1 * b) / a;
            
            if(y2 <= 0 || x2 <= 0){puts("0");continue;}
            ll t = (x2 - x1) / deltax + 1;
            if(t <= P)printf("%I64d
    ", t);
            else puts("ZenMeZheMeDuo");
        }
    }
    View Code

    第二题:原题,考虑边的贡献,注意背包顺序,有搞了好久;

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    const int M = 2005;
    const ll inf = -1e8;
    int h[M], siz[M], tot;
    ll dp[M][M];
    int n, m;
    struct edge{int v, nxt, w;}G[M << 2];
    void add(int u, int v, int w){
        G[++tot].v = v; G[tot].w = w; G[tot].nxt = h[u]; h[u] = tot;
    }
    
    void dfs(int u, int f){
        dp[u][0] = dp[u][1] = 0;
        siz[u] = 1;
        int child = 0;
        for(int i = h[u]; i; i = G[i].nxt){
            int v = G[i].v;
            if(v == f)continue;
            dfs(v, u);
            child++;
            siz[u] += siz[v];
            for(int k = min(siz[u], m); k >= 0; k--)
                for(int kk = 0; kk <= min(siz[v], k); kk++){
                    if(dp[u][k - kk] > inf){
                        ll val = 1LL*(1LL* kk * (m - kk) + 1LL * (siz[v] - kk) * (n - siz[v] - m + kk) ) * G[i].w;
                        dp[u][k] = max(dp[u][k], dp[u][k - kk] + dp[v][kk] + val);
                    }
                        
                }
            
        }
    
    //    printf("
    %d ",u);
    //    for(int i = 0; i <= m; i++)printf(" %I64d", dp[u][i]);
    }
    
    
    int main(){
        freopen("coloration.in","r",stdin);
        freopen("coloration.out","w",stdout);
        scanf("%d%d", &n, &m);
        memset(dp, 0x8f, sizeof(dp));
        int u, v, w;
        for(int i = 1; i < n; i++){
            scanf("%d%d%d", &u, &v, &w);
            add(u, v, w); add(v, u, w);
        }
        dfs(1, 0);
        printf("%I64d
    ", dp[1][m]);
    }
    View Code

    第三题:70的模拟分,我一分都没拿到,我一直在边上弄,其实应该在格点上做,就没有这么多边缘问题了;

    100分:

    光线只有遇上边界或堵塞的格子才会改变方向,所以改变方向的位置是有限的,光线的方向又最多只有四种,所以光线在循环之前改变方向的次数是O(n+m+k)级别的。我们可以模拟光线的移动。已知光线位置和光线的方向,使用二分的方法可以在O(log k)的时间复杂度内求出即将改变方向的位置和改变后的方向。

    我们对网格进行染色,有邻边的格子颜色不同,形成一个二分图。根据题目中光线反射的方式,可以发现,每当光线沿西北、东南方向前进时,只会经过一种颜色的网格,每当光线沿东北、西南方向前进时,只会经过另一种颜色的网格。所以光线在某一个格子中心时,要么只会是西北、东南方向之一,要么只会是东北、西南方向之一,就不会出现交叉的情况;

    这样,如果一次循环内一个格子被重复经过,只有可能是光线以相反的两个方向进入,并且一次循环内一个格子最多被经过两次。一个格子被经过两次,所有被光线经过的格子都会被经过两次。易知,如果光线在前进过程中出现过如下两种反射,所有格子就会被经过两次。只需在模拟的过程中记录是否出现过这两种情况即可。

     

    对于二分,由于对角线颜色一样,我们可以对对角线开vector存障碍,对角线x+y或y-x是不变的,可以作为编号;

    #include<bits/stdc++.h>
    using namespace std;
    //const int M = ;
    long long ans, f = 1;
    int x, y, dx, dy;
    
    struct node{
        int id, x;
        bool operator < (const node &rhs)const{
            return id == rhs.id ? x < rhs.x : id < rhs.id;
        }
    };
    vector <node> a[3];
    void add(int x, int y){
        a[0].push_back((node){x + y, x});
        a[1].push_back((node){x - y, x});
    }
    
    int zxxx;
    void wrk(){
        int fl = (dx == dy);
        node p; p.x = x;
        p.id = fl ? x - y : x + y;
        vector<node>::iterator it = upper_bound(a[fl].begin(), a[fl].end(), p);
        for(; it->id != p.id; it--);
        if(dx < 0) for(; it->x >= p.x; it--);
        //printf("%d %d hahaha
    ",it->id,it->x);
        ans += abs(it->x - x) - 1;
        x = it->x, y = fl ? x - it->id : it->id - x;
        
        bool u = binary_search(a[1].begin(), a[1].end(), (node){x - y - dx, x - dx});
        bool v = binary_search(a[1].begin(), a[1].end(), (node){x - y + dy, x});
        if(u == v) f = 2, dx *= -1, dy *= -1;
        else if(u) dy *= -1, x -= dx;
        else if(v) dx *= -1, y -= dy;
        //printf("%d %d %d %d %d
    ", x,y,dx,dy,ans);zxxx++;
    }
    
    
    
    int main(){
        freopen("ray.in","r",stdin);
        freopen("ray.out","w",stdout);
        int n, m, k, u, v;
        char opt[5];
        scanf("%d%d%d", &n, &m, &k);
        for(int i = 1; i <= n; i++)
            add(i, 0), add(i, m+1);
        for(int i = 0; i <= m+1; i++)
            add(0, i), add(n+1, i);
        for(int i = 1; i <= k; i++){
            scanf("%d%d", &u, &v);
            add(u, v);
        }
        sort(a[0].begin(), a[0].end());
        sort(a[1].begin(), a[1].end());
        scanf("%d%d", &x, &y);
        scanf("%s", opt);
        
        dx = (opt[0] == 'N') ? -1 : 1;
        dy = (opt[1] == 'E') ? 1 : -1;
        wrk();
        ans = 0;
        int sx = x, sy = y, zx = dx, zy = dy;
        do wrk();
        while(!(x == sx && y == sy && dx == zx && dy == zy));
        printf("%lld
    ", ans/f);
    } 
    View Code

    开学了……O__O"…

  • 相关阅读:
    双边沿采样
    `ifdef、`else、`endif 用法
    交通信号灯
    异步复位同步释放
    用Verilog来实现d触发器2分频的Verilog hdl程序
    谈谈Mux与门电路的相互替换(包含实例分析)
    数字电路笔试题
    仰视奶牛
    单调栈
    div2 620 C
  • 原文地址:https://www.cnblogs.com/EdSheeran/p/9573715.html
Copyright © 2020-2023  润新知