ACM-ICPC Asia Beijing Regional Contest 2018 Reproduction hihocoder1870~1879

ACM-ICPC Asia Beijing Regional Contest 2018 Reproduction hihocoder1870~1879

A

Sign, dfs or floyd do.

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

typedef long long LL;
typedef long double LD;
typedef pair<int,int> pii;
typedef pair<LL,int> pli;
const int SZ = 1e5 + 10;
const int INF = 1e9 + 10;
const int mod = 1e9 + 7;
const LD eps = 1e-8;

LL read() {
    LL n = 0;
    char a = getchar();
    bool flag = 0;
    while(a > '9' || a < '0') { if(a == '-') flag = 1; a = getchar(); }
    while(a <= '9' && a >= '0') { n = n * 10 + a - '0',a = getchar(); }
    if(flag) n = -n;
    return n;
}

string S1[22],S2[22];
int n;
int f[111][111];

void work() {
    map<string,int> mp;
    int tot = 0;
    for(int i = 1;i <= n;i ++) {
        string s1 = S1[i],s2 = S2[i];
        if(!mp[s1]) mp[s1] = ++ tot;
        if(!mp[s2]) mp[s2] = ++ tot;
    }

    for(int i = 1;i <= tot;i ++) {
        for(int j = 1; j <= tot;j ++) {
            f[i][j] = 0;
        }
    }

    for(int i = 1;i <= n;i ++) {
        string s1 = S1[i],s2 = S2[i];
        int x = mp[s1],y = mp[s2];
        if(f[y][x]) {
            cout << s1 << " " << s2 << endl;
            return ;
        }
        f[x][y] = 1;
        for(int k = 1;k <= tot;k ++) {
            for(int u = 1;u <= tot;u ++) {
                for(int v = 1;v <= tot;v ++) {
                    if(f[u][k] && f[k][v]) {
                        f[u][v] = 1;
                    }
                }
            }
        }
        for(int u = 1;u <= tot;u ++) {
            for(int v = 1;v <= tot;v ++) {
                if(f[u][v]) {
                    if(u == v || f[v][u]) {
                        cout << s1 << " " << s2 << endl;
                        return ;
                    }
                }
            }
        }
       /* for(int u = 1;u <= tot;u ++,puts(""))
            for(int v = 1;v <= tot;v ++)
                printf("%d ",f[u][v]);
        puts("");*/
    }
    puts("0");
    return ;
}

int main() {
    while(~scanf("%d",&n)) {
        for(int i = 1;i <= n;i ++) {
            string s1,s2;
            cin >> s1 >> s2;
            S1[i] = s1;
            S2[i] = s2;
        }
        work();
    }
}

B

Read the title, simulation, pit o'clock, WA a lot of hair, changed the wording pass by, do not know why

C

The meaning of problems: the definition (a, b, c) is a set of Pythagorean number, c is the length of the hypotenuse, and (a, b, c) and (b, a, c) seen as a group. Q c <triples the number of = n. \ (n \ le 10 ^ 9 \)

key: Push formula

I was really scared, why should the board will be out of this with a title.

First you have to know the number of Pythagorean structure in order to do this problem, namely \ (A = m ^ 2 ^-the n-2, b = 2mn, c = m ^ 2 + the n-^ 2 \) . All count the number of Pythagorean bad, so we Primitive Pythagorean count, multiplied by a multiplier can be. In the above formula, \ ((A, B, C) \) when a group of Primitive Pythagorean and only if \ (\ gcd (m, n ) = 1 \ text { and $ m, n $ is a odd one even} \) .

Set \ (F (n) \) is the triplet to the number n of the oblique, \ (G (n) \) is the number of n is the number of primitive Pythagorean hypotenuse, \ (F., G \) corresponding prefixes and then have:
\ [F = G \ Times. 1 \ F. to = \ sum_ {. 1 \ Le I \} G n-Le (n-/ I) \\ G (n-) = \ sum_ { 1 \ le x \ le N} \ sum_ {1 \ le y \ le N} [x ^ 2 + y ^ 2 \ le N] [\ gcd (x, y) = 1] [\ text {x is odd, y is even}] \]
and then just push the G wave on the line. Form a harmonic series.

If not preprocessed complexity is \ (O (Tn ^ {3/4} \ n-LN) \) , the complexity of the two-thirds power of the pretreatment root becomes \ (O (Tn ^ { } 2/3 \ n-LN) \) . G directly using this pretreatment given above, calculated at random integration complexity is pretreated before item B \ (O (B \ B LN) \) . Measured probably take a bit \ (10 ^ 7 \) comparative advantages, ten groups \ (10 ^ 9 \) ran only about 0.6s.

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

typedef unsigned long long ULL;
typedef long long LL;
typedef long double LD;
typedef pair<int,int> pii;
typedef pair<LL,int> pli;
const int SZ = 1e7 + 10;
const int INF = 1e9 + 10;
const int mod = 1e9 + 7;
const LD eps = 1e-8;

LL read() {
    LL n = 0;
    char a = getchar();
    bool flag = 0;
    while(a > '9' || a < '0') { if(a == '-') flag = 1; a = getchar(); }
    while(a <= '9' && a >= '0') { n = n * 10 + a - '0',a = getchar(); }
    if(flag) n = -n;
    return n;
}

int preG[SZ];
const int MAXN = 1e7;
int mu[100100];
bool vis[100100];
int pri[100100];

void preWork(int n) {
    for(int x = 1;x * x <= n;x += 2) {
        for(int y = 2;x * x + y * y <= n;y += 2) {
            if(__gcd(x,y) == 1)
                preG[x*x+y*y] ++;
        }
    }
    for(int i = 1;i <= n;i ++) preG[i] += preG[i-1];

    n = 100000;
    mu[1] = 1;
    for(int i = 2;i <= n;i ++) {
        if(!vis[i]) pri[++ pri[0]] = i,mu[i] = -1;
        for(int j = 1,m;j <= pri[0] && (m=i*pri[j]) <= n;j ++) {
            vis[m] = 1;
            if(i%pri[j] == 0) {
                mu[m] = 0;
            }
            else {
                mu[m] = -mu[i];
            }
        }
    }
}

LL G(int n) {
    if(n <= MAXN) return preG[n];
    LL ans = 0;
    for(int d = 1;d * d * 2 <= n;d ++) {
        int tmp = 0;
        int d2 = d*d,m = n/d2;
        for(int x = 1,lim = sqrt(n-d*d)/d;x*x <= m;x ++) {
            while(lim*lim+x*x > m) lim --;
            if((d*x)&1) tmp += lim / 2;
            else tmp += lim;
        }
        ans += mu[d] * tmp;
    }
    return ans / 2;
}

int main() {
   // freopen("C.in","r",stdin);
    preWork(MAXN);
    int T = read();
    while(T --) {
        int n = read();
        LL ans = 0;
        for(int i = 1,r;i <= n;i = r + 1) {
            r = n / (n / i);
            ans += G(n / i) * (r-i+1);
        }
        printf("%lld\n",ans);
    }
}
/**
3080075432
*/

D

Meaning of the questions: Do you want to jump 200 0, the i-th position can jump on the first i + 1 and i + 2. You can set the number of portal, a position only one entrance, exit any. Skip to the entrance to immediately transferred to the exit, form a ring if you never get out. Seeking the number of programs that go to 200 is exactly arranged as a set of programs M of transfer gate. \ (M <2 ^ {32 } \)

key: construction

If you want to ban out of a position, then it must be the best place transfer. Consider the i-th position out ban, then let the first i-1 is the number of program locations x, then the number of programs starting from the first 1 i-a \ (x, 0, x, x, 2x \) . In this way it is easy to think of the binary.

To Couchu \ (I ^ 2 \) , it should be set to \ (I ^ 2, X-, I ^ 2, 2 ^ I, I + 2 ^ {}. 1, the Y \) . If not, then it should be \ (I ^ 2, 2 ^ I, I + 2 ^ {}. 1, the Y \) . Wherein X is transmitted to the end, Y is transmitted in situ.

#include<bits/stdc++.h>
#define ll long long
#define pa pair<int,int>
using namespace std;
ll m;
ll f[304];
vector<pa>ans;
int w33ha(){
    ans.clear();
    memset(f,0,sizeof(f));
    f[0]=1;
    f[1]=1;
    //int a=0;
    int B = 0;
    for(ll i=0;i<=32;i++){
        if((m&(1LL<<i))){
            ans.push_back({B+1,199});
            ans.push_back({B+5,B+5});
            B += 6;
        }
        else{
            ans.push_back({B+3,B+3});
            B += 4;
        }
    }
    ans.push_back({197,197});
    ans.push_back({198,198});
    printf("%d\n",ans.size());
    for(int i=0;i<ans.size();i++){
        printf("%d %d\n",ans[i].first,ans[i].second);
    }
    return 0;
}

int main(){
    while(scanf("%lld",&m)!=EOF)w33ha();
    return 0;
}

E

Cluck

F

Meaning of the questions: to have a legitimate when directed graph, defined (u, v) if and only if u can come to v, the right value of u ^ v. Q twice to ask ask each k-th largest weights. \ (n \ le 5 * 10 ^ 4, m \ le 2 * 10 ^ 5, Q \ le 10, T \ le 3, k \ le 10 ^ 9 \)

key:bitset

The answer is easy to think half the problem is that check. If we deal with what can come out of the point x point, this collection is a set S, then to find how many \ (the y-\ in S \) , so that x ^ y> mid. This is done in the trie. So you do not have half the answer, greedy directly on the trie.

Consider walk from trie process: Piggy choose 0, if not, then go 1. It determines whether or not a sub-tree and, which is the range interval and, so now the question becomes equal to the number smaller than a numeral query number.

So there is a practice of the bitset. With tarjan + complexity topological sort pretreatment bitset is \ (O ((n-+ m) n-/ W is) \) , the complexity of the analog trie is \ (O (n-^ 2 / W is \ log n-) \) , the latter should not do.

So handwriting bitset, for n / W bit and build a prefix. The complexity of the latter \ (O (n-\ log n-) \) , the need to use __builtin_popcountll.

Therefore, the total complexity of the problem is \ (O (T ((n-m +) n-/ W is Qn + \ log n-)) \) , the spatial complexity degree \ (O (n ^ 2 / W) \)

(Here handwritten bitset, due to the nature of the difference it into a prefix and, due to the complexity of the __builtin_popcountll optimized queries. If not, then the binary number 1 of the complexity of the query again take a W, if not the nature of difference can block on the bitset)

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

typedef unsigned long long ULL;
typedef long long LL;
typedef long double LD;
typedef pair<int,int> pii;
typedef pair<LL,int> pli;
const int SZ = 5e4 + 10;
const int INF = 1e9 + 10;
const int mod = 1e9 + 7;
const LD eps = 1e-8;

LL read() {
    LL n = 0;
    char a = getchar();
    bool flag = 0;
    while(a > '9' || a < '0') { if(a == '-') flag = 1; a = getchar(); }
    while(a <= '9' && a >= '0') { n = n * 10 + a - '0',a = getchar(); }
    if(flag) n = -n;
    return n;
}

struct Bitset {
    #define W (64)

    int n;
    ULL bits[SZ / W + 10];
    int num[SZ / W + 10];

    void preWork() {
        for(int i = 0;i <= n/W;i ++) num[i] = __builtin_popcountll(bits[i]);
        for(int i = n/W-1;i >= 0;i --) num[i] += num[i+1];
     //  for(int i = 0;i < m;i ++) printf("%d ",sum[i]); puts("");
      //  for(int i = 0;i <= n/W;i ++) printf("%llu ",bits[i]); puts("");
    }

    int ask(int x) {
        if(x > n) return 0;
        int blockid = x / W;
        int ans = __builtin_popcountll(bits[blockid]>>(x%W));
        blockid ++;
        if(blockid <= n/W) ans += num[blockid];
        return ans;
    }

    int ask(int l,int r) {
        return ask(l) - ask(r+1);
    }

    void Or(const Bitset &t) {
        for(int i = 0;i <= n / W;i ++) bits[i] |= t.bits[i];
    }

    void Copy(const Bitset &t) {
        n = t.n;
        for(int i = 0;i <= n / W;i ++) bits[i] = t.bits[i];
    }

    void Set(int x) {
        bits[x/W] |= 1llu << (x%W);
    }

    void init(int nn) {
        n = nn; //n ++;
        for(int i = 0;i <= n / W;i ++) bits[i] = 0;
    }

    void print() {
        for(int i = 0;i < n;i ++) {
            if(bits[i/W] >> (i%W) & 1)
                printf("%d ",i);
        }
        puts("");
    }

    #undef W
}bs[SZ];

struct Tarjan {

    int n;
    int dfn[SZ],low[SZ],dfs_clock,scccnt,sccnum[SZ];
    vector<int> g[SZ],sccnodes[SZ];
    stack<int> S;

    void dfs(int u) {
        dfn[u] = low[u]= ++ dfs_clock;
        S.push(u);
        for(int v : g[u]) {
            if(!dfn[v]) {
                dfs(v);
                low[u] = min(low[u],low[v]);
            }
            else if(!sccnum[v])
                low[u] = min(low[u],dfn[v]);
        }
        if(low[u] == dfn[u]) {
            scccnt ++;
            while(1) {
                int x = S.top(); S.pop();
                sccnum[x] = scccnt;
                sccnodes[scccnt].push_back(x);
                if(x == u) break;
            }
        }
    }

    vector<int> g2[SZ];
    int cd[SZ];

    void work(Bitset bs[]) {
        for(int i = 1;i <= n;i ++)
            if(!dfn[i])
                dfs(i);
      //  for(int u = 1;u <= n;u ++) printf("%d ",sccnum[u]); puts("");
        for(int u = 1;u <= n;u ++)
            for(int v : g[u])
                if(sccnum[u] != sccnum[v]) {
                    g2[sccnum[v]].push_back(sccnum[u]);
                    cd[sccnum[u]] ++;
                }
        static Bitset tmp[SZ];
        for(int i = 1;i <= scccnt;i ++) {
            tmp[i].init(n); //tmp[i].print();
            for(int x : sccnodes[i])
                tmp[i].Set(x);
        }
        queue<int> q;
        for(int i = 1;i <= scccnt;i ++)
            if(cd[i] == 0) {
                q.push(i);
            }
        while(q.size()) {
            int v = q.front(); q.pop();
           // printf("%d: ",v); tmp[v].print();
            for(int x : sccnodes[v]) bs[x].Copy(tmp[v]);
            for(int u : g2[v]) {
                tmp[u].Or(tmp[v]);
                cd[u] --;
                if(cd[u] == 0) {
                    q.push(u);
                }
            }
        }
    }

    void addEdge(int x,int y) {
        g[x].push_back(y);
    }

    void init(int nn) {
        n = nn;
        for(int i = 1;i <= scccnt;i ++) {
            g2[i].clear();
            sccnodes[i].clear();
            cd[i] = 0;
        }
        for(int i = 1;i <= n;i ++) {
            g[i].clear();
            dfn[i] = low[i] = sccnum[i] = 0;
        }
        scccnt = 0;
        dfs_clock = 0;
    }

}tarjan;

int now[SZ];

void work(int n,int &mid,int id,int &k) {
    LL ans = 0;
    for(int i = 1;i <= n;i ++) {
        int t,l,r;
        if(i>>id&1)
            t = bs[i].ask(l=now[i],r=now[i]+(1<<id)-1);
        else
            t = bs[i].ask(l=now[i]+(1<<id),r=now[i]+(2<<id)-1);
        ans += t;
     //   printf("%d: [%d,%d] %d\n",i,l,r,t);
    }
    //cout << id << " " << ans << " " << k << endl;
    if(k <= ans) {
        for(int i = 1;i <= n;i ++) {
            if((i>>id&1) == 0) {
                now[i] |= 1 << id;
            }
        }
        mid |= 1 << id;
    }
    else {
        k -= ans;
        for(int i = 1;i <= n;i ++) {
            if(i>>id&1) {
                now[i] |= 1 << id;
            }
         }
    }
    //cout << k << endl;
   // for(int i = 1;i <= n;i ++) printf("%d ",now[i]); puts("");
}

int main() {
   // freopen("F.in","r",stdin); freopen("my.out","w",stdout);
    int T = read();
    while(T --) {
        int n = read(),m = read(),Q = read();
        tarjan.init(n);
        for(int i = 1;i <= m;i ++) {
            int x = read(),y = read();
            tarjan.addEdge(x,y);
        }
        tarjan.work(bs);
//        for(int i = 1;i <= n;i ++) bs[i].print();
        for(int i = 1;i <= n;i ++){
            bs[i].preWork();
        }
        while(Q --) {
            int k = read();
            int ans = 0;
            for(int i = 1;i <= n;i ++) now[i] = 0;
            for(int i = 16;i >= 0;i --) {
                work(n,ans,i,k);
            }
            printf("%d\n",ans);
        }
    }
}

G

The meaning of problems: a polynomial of degree n to F, find a polynomial of order n G, such that each root (not necessarily real roots) G into corresponding m-th power root of F. \ (n-m + \ Le 10, | a_i | \ Le 120 \) , to ensure the coefficient G \ (<10 ^ {12} \)

H

The meaning of problems: A nearly matched string B is defined if and only if there is a substring B with the same length A and up to a different character. Given A, find the number of length m B. Character set is {0,1}. \ (| A |, m \ le 40 \)

key:dp

The main fear of re-count, this just need to find the first match location. \ (f_ {i, j} \) represents the position of the first occurrence in the first A \ ([i- | A | + 1, i] \) and the j-th bit of the number of different schemes, there are:
\ [F_ {I, j} = 2 ^ {i- | A |} - \ sum_ {k \ le i- | A |, l} f_ {k, l} \ times 2 ^ {i- | A | -k} - \ sum_ { i- | a | <k <i
} f_ {k, l} \ times w (i, j, k, l) \] i.e. just fill the front subtracting appeared. The first is the number of the current position does not intersect the string occurs, the second term is the number of intersection. Note that the intersection may not be legal, the need for a \ (w (i, j, k, l) \) to Check, legitimate returns 1, and 0 otherwise. This can be pre-out. The total complexity is \ (O (m ^ 2 | A | ^ 2) \)

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

typedef long long LL;
typedef long double LD;
typedef pair<int,int> pii;
typedef pair<LL,int> pli;
const int SZ = 1e5 + 10;
const int INF = 1e9 + 10;
const int mod = 1e9 + 7;
const LD eps = 1e-8;

LL read() {
    LL n = 0;
    char a = getchar();
    bool flag = 0;
    while(a > '9' || a < '0') { if(a == '-') flag = 1; a = getchar(); }
    while(a <= '9' && a >= '0') { n = n * 10 + a - '0',a = getchar(); }
    if(flag) n = -n;
    return n;
}

char s[55];
int n,m;
LL f[55][55];
LL g[55][55][55];

bool isequ(int len,int p1,int p2) {
    string s1,s2;
    for(int i = 1;i <= len;i ++) {
        if(i==p1) {
            if(s[i] == '0') s1 += '1';
            else s1 += '0';
        }
        else s1 += s[i];
    }
    for(int i = n-len+1;i <= n;i ++) {
        if(i==p2) {
            if(s[i] == '0') s2 += '1';
            else s2 += '0';
        }
        else s2 += s[i];
    }
    return s1 == s2;
}

int main() {
    int T = read();
    while(T --) {
        n = read(),m = read();
        scanf("%s",s+1);
        for(int j = 0;j <= n;j ++) {
            for(int k = 1;k < n;k ++) {
                for(int l = 0;l <= n;l ++) {
                    if(isequ(k,j,l)) {
                        g[j][k][l] = 1;
                    }
                    else {
                        g[j][k][l] = 0;
                    }
                }
            }
        }
        for(int i = 1;i <= m;i ++) {
            for(int j = 0;j <= n;j ++) {
                if(i-n < 0) {
                    f[i][j] = 0;
                    continue;
                }
                LL ans = 1ll<<(i-n);
                for(int k = 1;k < i;k ++) {
                    for(int l = 0;l <= n;l ++) {
                        if(k <= i-n) {
                            ans -= f[k][l] * (1ll<<(i-n-k));
                        }
                        else {
                            ans -= f[k][l] * g[j][k-i+n][l];
                        }
                    }
                }
                f[i][j] = ans;
            }
        }
        LL ans = 0;
        for(int i = 1;i <= m;i ++) {
            for(int j = 0;j <= n;j ++) {
                ans += f[i][j] * (1ll<<(m-i));
            }
        }
        printf("%lld\n",ans);
    }
}

I

Hit the table to find the law

J

The meaning of problems: given n points on a two dimensional plane, find the sum of all acute triangle area. \ (n \ le 2000 \)

key: scanning lines

The total area of ​​the right triangle area minus minus obtuse triangle area. The three double pointer can be positioned on the polar angle ordered sequence. Operators with the prefix area and on the line.

Guess you like

Origin www.cnblogs.com/dqsssss/p/11514612.html