zoukankan      html  css  js  c++  java
  • TopCoder SRM 633div1

    250pts   PeriodicJumping

     题意:从起点开始,每次按找数组jump给定的长度,即jump[0], jump[1], jump[2].....jump[n-1], 向各个方向跳,跳完后从从头开始,问最后能否达到(x,0).

    限制:|x| <= (int)1e9,n <= 50, 1 <= len[i] <= (int)1e9.

    分析:

    题解分析的很详细,每次跳完后可达的范围离原点的距离总是一个区间[a,b],考虑下一次跳的长度r之后,可达的范围,

    (1). r < a, a = a-r;

    (2). a <= r <= b, a = 0;

    (3). r > b , a = r-b;

    而b不论r取值如何总是变为b+r.一个周期内跳跃总长度为S,那么一开始连续跳跃两个周期,看做两次跳跃长度都是S, 可达范围是[0,2S],求出在到达x之前最多跳跃多少个2S,剩下的直接模拟,直到x在所到达的范围内即可.

    代码:

     1 #include <bits/stdc++.h>
     2 #define pb push_back
     3 #define mp make_pair
     4 #define esp 1e-14
     5 #define lson   l, m, rt<<1
     6 #define rson   m+1, r, rt<<1|1
     7 #define sz(x) ((int)((x).size()))
     8 #define pf(x) ((x)*(x))
     9 #define pb push_back
    10 #define pi acos(-1.0)
    11 #define in freopen("solve_in.txt", "r", stdin);
    12 #define bug(x) printf("Line : %u >>>>>>
    ", (x));
    13 #define TL cerr << "Time elapsed: " << (double)clock() / CLOCKS_PER_SEC * 1000 << " ms" << endl;
    14 #define inf 0x0f0f0f0f
    15 using namespace std;
    16 typedef long long LL;
    17 typedef unsigned US;
    18 typedef pair<int, int> PII;
    19 typedef map<PII, int> MPS;
    20 typedef MPS::iterator IT;
    21 vector<int> len;
    22 
    23 class PeriodicJumping {
    24 public:
    25     int minimalTime(int x, vector <int> jump) {
    26         LL tmp = 0;
    27         for(int y: jump)
    28             tmp += 2*y;
    29         x = abs(x);
    30         if(x == 0) return 0;
    31         int n = jump.size();
    32         int ans = 1LL*((x-1)/tmp)*n*2;
    33        LL a = 0, b = (x-1)/tmp*tmp;
    34         
    35         while(1) {
    36             for(int y:jump) {
    37                 
    38                 if(a > y) {
    39                     a = a-y;
    40                 } else if(y <= b) {
    41                     a = 0;
    42                 } else {
    43                     a = y-b;
    44                 }
    45                 b+=y;
    46                 ans++;
    47                 if(x >= a && x <= b)
    48                     break;
    49             }
    50             if(x >= a && x <= b)
    51                 break;
    52         }
    53         return ans;
    54     }
    55 };
    View Code

    500pts DoubleTree

    题意: 两棵树,共n个结点,对应编号的结点权值相同,可正可负,求从中选出一个结点结合,使得选出的集合在两棵树上都是一棵子树,即都联通,权值要求最大.

    限制:2 <= n <= 50, |权值 | <= 1000.

    分析:

    选出任意个结点构成一棵子树的条件时,这些结点间相互可达,也就是都能到达同一个结点,因为树中路径唯一,不妨把这个点当做根结点。

    依次考虑每个结点做根时,考虑剩下的结点选中时的情形,两棵树中这个结点到根路径上所有结点都要选中,这样又会引入一些选中的结点,总结起来就是,所有选中的结点在两棵树中到根的路径上其他结点都要选中。

    具体建图时,分别对两棵树dfs,每个节点到其父节点连边,当要选中这个结点时,必须从这个结点出发,将所有能达的点全部选中,同时使得权值和最大,问题就转化为最大权闭合图了。这个可以参考胡伯涛的论文。

    代码:

      1 #include <bits/stdc++.h>
      2 #define pb push_back
      3 #define mp make_pair
      4 #define esp 1e-14
      5 #define lson   l, m, rt<<1
      6 #define rson   m+1, r, rt<<1|1
      7 #define sz(x) ((int)((x).size()))
      8 #define pf(x) ((x)*(x))
      9 #define pb push_back
     10 #define pi acos(-1.0)
     11 #define in freopen("solve_in.txt", "r", stdin);
     12 #define bug(x) printf("Line : %u >>>>>>
    ", (x));
     13 #define TL cerr << "Time elapsed: " << (double)clock() / CLOCKS_PER_SEC * 1000 << " ms" << endl;
     14 #define inf 0x0f0f0f0f
     15 using namespace std;
     16 typedef long long LL;
     17 typedef unsigned US;
     18 typedef pair<int, int> PII;
     19 typedef map<PII, int> MPS;
     20 typedef MPS::iterator IT;
     21 const int maxn = 55;
     22 
     23 int src, sink;
     24 
     25 struct Edge {
     26     int u, v, c;
     27     Edge() {}
     28     Edge(int u, int v, int c):u(u), v(v), c(c) {}
     29 };
     30 
     31 struct MaxFlow {
     32     int n, m;
     33     vector<int> G[maxn];
     34     vector<Edge> edges;
     35     int Now[maxn], Dfn[maxn];
     36 
     37     void init(int n) {
     38         this->n = n;
     39         for(int i = 0; i < n; i++)
     40             G[i].clear();
     41         edges.clear();
     42     }
     43     void add(int u, int v, int c) {
     44    // cout << u << ' ' << v << endl;
     45         edges.pb(Edge(u, v, c));
     46         edges.pb(Edge(v, u, 0));
     47         m = edges.size();
     48         G[u].pb(m-2);
     49         G[v].pb(m-1);
     50     }
     51     int ISAP(int s, int flow) {
     52         if(s == sink) return flow;
     53         int now = 0, vary, tab = n, v;
     54         for(int i = 0; i < (int)G[s].size(); i++) {
     55             Edge &e = edges[G[s][i]];
     56             if(e.c > 0) {
     57                 if(Dfn[s] == Dfn[v = e.v] + 1)
     58                     vary = ISAP(v, min(flow-now, e.c)), now += vary,
     59                             e.c -= vary, edges[G[s][i]^1].c += vary;
     60                 if(Dfn[src] == n) return now;
     61                 if(e.c > 0) tab = min(tab, Dfn[v]);
     62                 if(flow == now) break;
     63             }
     64           }
     65             if(now == 0) {
     66                 if(--Now[Dfn[s]] == 0)
     67                     Dfn[src] = n;
     68                 Now[Dfn[s] = tab+1]++;
     69             }
     70 
     71         return now;
     72     }
     73     int getAns() {
     74         memset(Now, 0, sizeof Now);
     75         memset(Dfn, 0, sizeof Dfn);
     76         Now[0] = n;
     77         int ans = 0;
     78         while(Dfn[src] < n)
     79             ans += ISAP(src, inf);
     80         return ans;
     81     }
     82 } solver;
     83 
     84 class DoubleTree {
     85 public:
     86     int n;
     87     int g[maxn][maxn];
     88     vector<int> tree[2][maxn];
     89     int rt;
     90     void add(int id, int u, int v) {
     91 
     92         tree[id][u].pb(v);
     93         tree[id][v].pb(u);
     94     }
     95     void dfs(int id, int u, int fa) {
     96         if(fa != -1 && fa != rt) {
     97             g[u][fa] = 1;
     98         }
     99         for(int i = 0; i < sz(tree[id][u]); i++) {
    100             int v = tree[id][u][i];
    101             if(v == fa) continue;
    102             dfs(id, v, u);
    103         }
    104     }
    105     int maximalScore(vector <int> a, vector <int> b, vector <int> c, vector <int> d, vector <int> s) {
    106         n = sz(a)+1;
    107         int mx, z;
    108 
    109         for(int i = 0; i < n-1; i++) {
    110             add(0, a[i], b[i]);
    111             add(1, c[i], d[i]);
    112         }
    113         int ans = 0;
    114         src = n, sink = n+1;
    115 
    116         for(int i = 0; i < n; i++ ){
    117             mx = z = 0;
    118             memset(g, 0, sizeof g);
    119 
    120             for(int j = 0; j < n; j++) {
    121                 mx += (i != j ? abs(s[j]) : 0);
    122                 z += (i != j && s[j] > 0 ? s[j] : 0);
    123             }
    124             mx+=10;
    125             rt = i;
    126             dfs(0, i, -1);
    127             dfs(1, i, -1);
    128              //for(int ii = 0; ii < n; ii++, puts("")) for(int j = 0; j < n; j++)
    129          //  cout << g[ii][j] << ' ';
    130             solver.init(n+2);
    131             for(int u = 0; u < n; u++) {
    132                 if(u != rt) {
    133                     if(s[u] > 0) solver.add(src, u, s[u]);
    134                     else solver.add(u, sink, -s[u]);
    135                 }
    136                 for(int v = 0; v < n; v++) {
    137                     if(!g[u][v]) continue;
    138                     solver.add(u, v, mx);
    139                 }
    140             }
    141 
    142             ans = max(ans, z-solver.getAns()+s[i]);
    143         }
    144         return ans;
    145     }
    146 };
    147 int main(){
    148     return 0;
    149 }
    150 
    151 
    152 // Powered by FileEdit
    View Code

    1000pts GCDLCM 

    题意:现有n个正整数,给出4个数组,描述x[A[i]],x[B[i]],的LCM或GCD为C[i],问能否找到这样一组正整数。

    n <= 200, m <= 200.

    分析:GCD要求A[i],B[i]的相应质因子p的个数最小值 = m(m为C[i]包含的质因子p的个数), 即min(A[i], B[i]) = m。即A[i] = m && B[i] >= m 或 B[i] = m && A[i] >= m.LCM则是将min改为max.

    这样对C[]分解质因数后,单独考虑其中每个质因子的问题,对A[i], B[i], C[i]分析可得到一系列条件, 将A[i] = m && B[i] >= m , B[i] = m && A[i] >= m 分别看成X,Y表达式,原来的GCD[i]或LCM[i]问题变成了,X[i]或Y[i]的表达式,注意对于每个i,X[i]和Y[i]中至少有一个成立,当然可以有两个同时成立,然后便是X[i],Y[i],X[j],Y[j]中必然会存在矛盾,处理一下,最后用2-sat解决.

    代码:

    #include <bits/stdc++.h>
    #define pb push_back
    #define mp make_pair
    #define esp 1e-14
    #define lson   l, m, rt<<1
    #define rson   m+1, r, rt<<1|1
    #define sz(x) ((int)((x).size()))
    #define pf(x) ((x)*(x))
    #define pb push_back
    #define pi acos(-1.0)
    #define in freopen("solve_in.txt", "r", stdin);
    #define bug(x) printf("Line : %u >>>>>>
    ", (x));
    #define TL cerr << "Time elapsed: " << (double)clock() / CLOCKS_PER_SEC * 1000 << " ms" << endl;
    #define inf 0x0f0f0f0f
    using namespace std;
    typedef long long LL;
    typedef unsigned US;
    typedef pair<int, int> PII;
    typedef map<PII, int> MPS;
    typedef MPS::iterator IT;
    
    const int maxn = 800 + 10;
    //2-sat
    struct twoSat {
        int n;
        int mark[maxn], S[maxn];
        vector<list<int> > g;
        int c;
        void init(int n) {
            this->n = n;
            g.resize(n*2);
            for(auto &x:g)
                x.clear();
            memset(mark, 0, sizeof mark);
        }
        void add(int x, int y) {
            g[x].pb(y);
        }
        bool dfs(int x) {
            if(mark[x^1]) return false;
            if(mark[x]) return true;
            S[c++] = x;
            mark[x] = 1;
            for(int y: g[x]) {
                if(!dfs(y)) return false;
            }
            return true;
        }
        bool solve() {
            for(int i = 0; i < n*2; i += 2) {
                if(!mark[i] && !mark[i+1]) {
                    c = 0;
                    if(!dfs(i)) {
                        while(c) mark[S[--c]] = 0;
                        if(!dfs(i+1)) return false;
                    }
                }
            }
            return true;
        }
    } solver;
    struct State {
        int a, b, c, d;
        State() {}
        State(int a, int b, int c, int d):a(a), b(b), c(c), d(d) {}
    };
    vector<State> sta;
    
    class GCDLCM {
    public:
        set<int> div;//relevant primes
        vector<PII> factor[200 + 10];
        //get prime factor of n, store in vec
        void getPrimeFac(int n) {
            for(int i = 2; i <= n/i; i++) {
    
                if(n%i == 0) {
                    while(n%i == 0) {
                        n /= i;
                    }
                    div.insert(i);
                }
            }
            if(n != 1) {
                div.insert(n);
            }
        }
        bool contradiction(int x, int y) {
            int a0 = sta[x].a, b0 = sta[x].b, c0 = sta[x].c, d0 = sta[x].d;
            int a1 = sta[y].a, b1 = sta[y].b, c1 = sta[y].c, d1 = sta[y].d;
            if(a0 == a1 && c0 != c1) {
                return true;
            }
            if(a0 == b1 && ((d1 && c0 < c1) || (!d1 && c0 > c1))) {
                return true;
            }
            if(b0 == a1 && ((d0 && c1 < c0) || (!d0 && c1 > c0))) {
                return true;
            }
            if(b0 == b1 && ((d0 > d1 && c0 > c1) || (d0 < d1 && c0 < c1))) {
                return true;
            }
            return false;
        }
        string possible(int n, string type, vector <int> A, vector <int> B, vector <int> C) {
            int m = sz(A);
            for(int i = 0; i < m; i++)
                getPrimeFac(C[i]);
            for(int u: div) {
                sta.clear();
                for(int j = 0; j < m; j++) {
                    int r = 0;
                    int y = C[j];
                    while(y%u == 0) {
                        r++;
                        y /= u;
                    }
                    sta.pb(State(A[j], B[j], r, type[j] == 'G'));
                    sta.pb(State(B[j], A[j], r, type[j] == 'G'));
                }
    
                solver.init(sz(sta));
                //add edge x->~y, ~y->x,etc.
                for(int i = 0; i < sz(sta); i += 2) {
                    //solver.add(i<<1, (i+1)<<1|1);
                    solver.add((i+1)<<1|1, i<<1);
                    //solver.add((i+1)<<1, i<<1|1);
                    solver.add(i<<1|1, (i+1)<<1);
                }
                for(int i = 0; i < sz(sta); i++) for(int j = 0; j < sz(sta); j++) {
                        if(contradiction(i, j)) {
                            solver.add(i<<1, j<<1|1);
                            solver.add(j<<1, i<<1|1);
                        }
                    }
                if(!solver.solve()) return  "Solution does not exist";
            }
            return  "Solution exists";
        }
    };
    View Code

     学习了一下list,和vector最大区别便是不支持随机存取,可以看做是STL中的双向链表,支持首尾插入,删除。

  • 相关阅读:
    MYSQL查看数据表最后更新时间
    linux在终端模拟软件实现文件上传下载
    yum常用操作
    释放Linux占用端口
    CentOS7.3编译安装MariaDB10.2.6
    CentOS7编译安装Nginx1.10.1
    Linux系统安装ActiveMQ时遇到服务无法启动的问题
    需求分析读书笔记(一)
    实用地址分享
    元素居中汇总
  • 原文地址:https://www.cnblogs.com/rootial/p/4278606.html
Copyright © 2011-2022 走看看