CCPC2019 network game

2019 Chinese Collegiate Programming Contest (CCPC) - Trials Network

A

The meaning of problems: find the smallest positive integer such that C (A ^ C) & (B ^ C) minimum. \ (A, B \ le 10 ^ 9 \)

Attendance problems. The A & B taken when C is 0, and at this time is minimal. Note that to a positive integer, so keep a take max.

#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;
typedef pair<LL,LL> pll;
const int SZ = 1e6 + 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;
}

LL work(LL n,LL m) {
    for(LL k = 0;;k ++) {
        if(((n^k)&(m^k)) == 0) return k;
    }
}

int main() {
    int T = read();
    while(T --) {
        LL n,m;
        scanf("%lld%lld",&n,&m);
        printf("%lld\n",max(1ll,n&m));
    }
}

B

Question is intended: to one arrangement, each operation is given a \ (a_x = + 10. 7 ^ \) , or ask that it is greater than a minimum equal to v \ (K_i \) does not equal to any one \ (a_j \) , \ ((1 \ Le J \ Le r_i) \) . \ (k_i \ le n \ le 10 ^ 5 \)

key: segment tree

Range of built tree line, the position of each point of deposit appear that number. Every modification operations can actually be seen as a location appear in infinity. I.e., each time the right to find a minimum point x, such that the maximum value [k, x] is larger than r.

Since the segment tree comes dichotomy, it can be directly to the complexity of the \ (O (n \ log n ) \)

#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;
typedef pair<LL,LL> pll;
const int SZ = 1e6 + 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 a[SZ];

struct seg {
    int l,r,mx;
}tree[SZ * 4];

void update(int p) {
    tree[p].mx = max(tree[p<<1].mx,tree[p<<1|1].mx);
}

void build(int p,int l,int r) {
    tree[p].l = l;
    tree[p].r = r;
    if(l == r) {
        tree[p].mx = a[l];
        return ;
    }
    int mid = l + r >> 1;
    build(p<<1,l,mid);
    build(p<<1|1,mid+1,r);
    update(p);
}

void change(int p,int x,int d) {
    if(tree[p].l == tree[p].r) {
        tree[p].mx = d;
        return ;
    }
    int mid = tree[p].l + tree[p].r >> 1;
    if(x <= mid) change(p<<1,x,d);
    else change(p<<1|1,x,d);
    update(p);
}

int ask_max(int p,int l,int r) {
    if(l <= tree[p].l && tree[p].r <= r) {
        return tree[p].mx;
    }
    int mid = tree[p].l + tree[p].r >> 1,ans = 0;
    if(l <= mid) ans = max(ans,ask_max(p<<1,l,r));
    if(mid < r) ans = max(ans,ask_max(p<<1|1,l,r));
    return ans;
}

int n,m;

int ask(int p,int l,int v) {
   // printf("%d [%d,%d] %d %d\n",p,tree[p].l,tree[p].r,l,v);
    if(tree[p].l == l) {
        if(tree[p].l == tree[p].r) {
            if(tree[p].mx <= v) return -1;
        //    cout << tree[p].l << endl;
            return tree[p].l;
        }
     //   printf("%d\n",tree[p<<1].mx);
        if(tree[p<<1].mx > v) return ask(p<<1,l,v);
        int mid = tree[p].l + tree[p].r >> 1;
        return ask(p<<1|1,mid+1,v);
    }
    int mid = tree[p].l + tree[p].r >> 1;
    if(mid < l) {
        return ask(p<<1|1,l,v);
    }
    else {
        int ans = ask(p<<1,l,v);
        if(ans != -1) return ans;
        return ask(p<<1|1,mid+1,v);
    }
}

int b[SZ];

int main() {
   // freopen("02.out","w",stdout);
    int T = read();
    while(T --) {
        n = read(),m = read();
        for(int i = 1;i <= n;i ++) a[b[i] = read()] = i;
        build(1,1,n);
        int lstans = 0;
        while(m --) {
            int o = read();
            if(o == 1) {
                int x = read() ^ lstans;
                if(b[x] == 1e9) continue;
                change(1,b[x],1e9);
                b[x] = 1e9;
            }
            else {
                int r = read() ^ lstans,k = read() ^ lstans;
                int ans = ask(1,k,r);
                if(ans == -1) ans = n+1;
                printf("%d\n",lstans = ans);
            }
        }
    }
}

C

Meaning of the questions: to a string Always ask a sub-section of the k-th position in the string appear throughout the string. \ (n, Q \ le 10 ^ 5 \)

key: st table, suffix array, Chairman of the tree

Think suffix array on the same subject, there should be sam like practice, but I'm not in this range will be positioned position in the sam ......

Suffix array find the current range position in the lcp, find the range to the left and right rmq half, this string will appear in this section on each location, find the k Small is small static interval k, chairman sets a tree.

Find the interval when little details that need attention.

#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;
typedef pair<LL,LL> pll;
const int SZ = 1e6 + 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 SuffixArray {
    /// 串从0开始,a[len]是非法字符
    /// sa[i]表示排名为i的后缀 i在[0,len-1]
    /// lcp[i]表示sa[i]和sa[i-1]的lcp i在[1,len-1]
    int lcp[SZ],sa[SZ],rk[SZ],len;
    bool cmp(int *y,int a,int b,int k) {
        int a1 = y[a],b1 = y[b];
        int a2 = a + k >= len ? -1 : y[a + k];
        int b2 = b + k >= len ? -1 : y[b + k];
        return a1 == b1 && a2 == b2;
    }

    int t1[SZ],t2[SZ],cc[SZ];

    void get_sa(char s[],int m) {
        int *x = t1,*y = t2; /// 字符集
        for(int i = 0;i < m;i ++) cc[i] = 0;
        for(int i = 0;i < len;i ++) ++ cc[x[i] = s[i]];
        for(int i = 1;i < m;i ++) cc[i] += cc[i - 1];
        for(int i = len - 1;~i;i --) sa[-- cc[x[i]]] = i;
        for(int k = 1;k < len;k <<= 1) {
            int p = 0;
            for(int i = len - k;i < len;i ++)  y[p ++] = i;
            for(int i = 0;i < len;i ++) if(sa[i] >= k) y[p ++] = sa[i] - k;
            for(int i = 0;i < m;i ++) cc[i] = 0;
            for(int i = 0;i < len;i ++) ++ cc[x[y[i]]];
            for(int i = 1;i < m;i ++) cc[i] += cc[i - 1];
            for(int i = len - 1;~i;i --) sa[-- cc[x[y[i]]]] = y[i];
            swap(x,y); m = 1; x[sa[0]] = 0;

            for(int i = 1;i < len;i ++)
                x[sa[i]] = cmp(y,sa[i - 1],sa[i],k) ? m - 1 : m ++;
            if(m >= len) break;
        }
    }

    void get_lcp(char s[]) {
        for(int i = 0;i < len;i ++) rk[sa[i]] = i;
        int h = 0;
        lcp[0] = 0;
        for(int i = 0;i < len;i ++) {
            if(!rk[i]) continue;
            int j = sa[rk[i] - 1];
            if(h) h --;
            while(s[i + h] == s[j + h]) h ++;
            lcp[rk[i]] = h;
        }
    }

    void init(char *s,int n,int m) {
        len = n;
        get_sa(s,m); get_lcp(s);
    }
}sa;

int st[SZ][22];

void get_st(int a[],int n) {
    for(int i = 1;i <= n;i ++) st[i][0] = a[i];

    for(int j = 1;j <= log2(n);j ++) {
        for(int i = 1;i + (1<<j) - 1 <= n;i ++) {
            st[i][j] = min(st[i][j-1],st[i+(1<<(j-1))][j-1]);
        }
    }

  /*  for(int i = 1;i <= n;i ++) {
        for(int j = 0;j <= log2(n);j ++) {
            printf("%4d",st[i][j]);
        }
        puts("");
    }*/
}

int ask_min(int l,int r) {
    int k = log2(r-l+1);
    return min(st[l][k],st[r-(1<<k)+1][k]);
}

struct seg {
    int l,r,sz;
}tree[30000010];

int Tcnt = 0,rt[SZ];

void insert(int l,int r,int last,int &now,int v,int x) {
    now = ++ Tcnt;
    tree[now] = tree[last];
    tree[now].sz += x;
    if(l == r) return;
    int mid = (l + r) >> 1;
    if(v <= mid) insert(l,mid,tree[last].l,tree[now].l,v,x);
    else insert(mid + 1,r,tree[last].r,tree[now].r,v,x);
}

int ask_kth(int l,int r,int k) {
   // printf("[%d,%d] %d\n",l,r,k);
    if(r-l+1 < k) return -2;
    int L = 0,R = sa.len-1;
    int tl = rt[l-1],tr = rt[r];
    while(L != R) {
        int mid = L + R >> 1;
        int sz = tree[tree[tr].l].sz - tree[tree[tl].l].sz;
        if(sz >= k) {
            tl = tree[tl].l; tr = tree[tr].l; R = mid;
        }
        else {
            tl = tree[tl].r; tr = tree[tr].r; L = mid+1;
            k -= sz;
        }
    }
    return L;
}

pii ask(int p,int v) {
 //   cout << p << " " <<v << endl;
    pii ans;
    int L,R;
    if(sa.lcp[p] >= v) {
        L = 0,R = p;
        while(R - L > 1) {
            int mid = L + R >> 1;
         //   printf("[%d,%d] min: %d\n",mid,p,ask_min(mid,p));
            if(ask_min(mid,p) >= v) R = mid;
            else L = mid;
        }
        ans.first = R - 1;
    }
    else ans.first = p;

    L = p,R = sa.len;
    while(R - L > 1) {
        int mid = L + R >> 1;
        if(ask_min(p+1,mid) >= v) L = mid;
        else R = mid;
    }
    ans.second = L;
    return ans;
}

char s[SZ];

int main() {
    int T = read();
    while(T --) {
        int n = read(),m = read();
        scanf("%s",s);
        sa.len = strlen(s);
        sa.get_sa(s,256);
        sa.get_lcp(s);
/*
        for(int i = 0;i < sa.len;i ++) printf("%3d",i); puts("");
        for(int i = 0;i < sa.len;i ++) printf("%3d",sa.sa[i]); puts("");
        for(int i = 0;i < sa.len;i ++) printf("%3d",sa.lcp[i]); puts("");
        for(int i = 0;i < sa.len;i ++) printf("%3d",sa.rk[i]); puts("");
*/
        Tcnt = 0;
        for(int i = 1;i <= sa.len;i ++) insert(0,sa.len-1,rt[i-1],rt[i],sa.sa[i-1],1);

        get_st(sa.lcp,sa.len-1);

        while(m --) {
            int l = read(),r = read(),k = read();
            int ll = r - l + 1;
            l --;
            pii qj = ask(sa.rk[l],ll);
            printf("%d\n",ask_kth(qj.first+1,qj.second+1,k) + 1);
        }
    }
}
/**
233
5 5
aabaa
2 3 1

233
5 5
ababc
1 2 2
*/

D

Meaning of the questions: to a weighted directed graph, each time asking the k short path. \ (k, n, m, q \ le 5 * 10 ^ 4 \)

key: Heap

K see a small, think of a time out from a pile of expansion, multiple sets of asking offline just fine.

The first edge list sorted according to weight, each state memory (current point, the current of several side edge of the table, the length of the current), takes out one throw into two, namely the side of a table (if any) and the current point along this first side edge out the current edge of the table. Complexity \ (O (k \ log k ) \)

#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;
typedef pair<LL,LL> pll;
const int SZ = 1e6 + 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;
}

vector<pii> g[SZ];

struct haha {
    int u,id;
    LL w;
};

bool operator <(haha a,haha b) {
    return a.w > b.w;
}

struct hh {

    priority_queue<haha> q;

    void push(int u,int id,LL w) {
       // printf("%d %d %lld\n",u,id,w);
        q.push((haha){u,id,w});
    }

    haha top() {
        assert(q.size());
        return q.top();
    }

    void pop() {
        assert(q.size());
        haha f = q.top(); q.pop();
     //   printf("%d %d %lld:\n",f.u,f.id,f.w);
        int u = f.u,v = g[u][f.id].second;
        if(g[v].size()) {
            push(v,0,f.w+g[v][0].first);
        }

        f.w -= g[u][f.id].first;
        f.id ++;
        if(f.id < g[u].size())
            f.w += g[u][f.id].first,push(f.u,f.id,f.w);
      //  puts("----------");
    }

    void clr() {
        while(q.size()) q.pop();
    }
}q;


LL ans[SZ];
pii b[SZ];

int main() {
    int T = read();
    while(T --) {
        q.clr();
        int n = read(),m = read(),Q = read();
        for(int i = 1;i <= n;i ++) g[i].clear();
        for(int i = 1;i <= m;i ++) {
            int x = read(),y = read(),w = read();
            g[x].push_back(make_pair(w,y));
        }
        for(int i = 1;i <= n;i ++) sort(g[i].begin(),g[i].end());

        for(int i = 1;i <= n;i ++) {
            if(g[i].size())
                q.push(i,0,g[i][0].first);
        }
        for(int i = 1;i <= Q;i ++) {
            b[i].first = read();
            b[i].second = i;
        }
        sort(b+1,b+1+Q);
        int now = 1;
        for(int i = 1;i <= Q;i ++) {
            while(now < b[i].first) {
                q.pop();
                now ++;
            }
            //cout << now << endl;
            haha x = q.top();
            ans[b[i].second] = x.w;
        }
        for(int i = 1;i <= Q;i ++) printf("%lld\n",ans[i]);
    }
}

E

Question is intended: to n, a, b, computing
\ [f (n, a, b) = \ sum_ {i = 1} ^ n \ sum_ {j = 1} ^ i gcd (i ^ aj ^ a, i ^ bj ^ b) [gcd (i
, j) = 1] \% (10 ^ 9 + 7) \] wherein a, b coprime. \ (n, a, b \ le 10 ^ 9 \)

key: Inversion

Available play table, a, b and prime i, j when the equation gcd is the prime ij.

Then casually pushing to set a sieve Du teach

#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;
typedef pair<LL,LL> pll;
const int SZ = 5e6 + 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;
}

LL ksm(LL a,LL b) {
    LL ans = 1;
    while(b) {
        if(b&1) ans = a * ans;
        a = a * a;
        b >>= 1;
    }
    return ans;
}

LL ksm(LL a,LL b,LL p) {
    LL ans = 1;
    while(b) {
        if(b&1) ans = a * ans % p;
        a = a * a % p;
        b >>= 1;
    }
    return ans;
}

const int MAXN = 5e6;
const int ni2 = (mod+1)/2;
const int ni6 = ksm(6,mod-2,mod);

bool vis[SZ];
int pri[SZ],tot,mu[SZ],smud[SZ];

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

LL f1(LL n) {
    n %= mod;
    return n * (n + 1) % mod * ni2 % mod;
}

LL f2(LL n) {
    n %= mod;
    return n * (n + 1) % mod * (2*n+1) % mod * ni6 % mod;
}

LL f3(LL n) {
    return f1(n) * f1(n) % mod;;
}

unordered_map<int,int> smd;

int dfs(int n) {
    if(n <= MAXN) return smud[n];
    if(smd.count(n)) return smd[n];
    LL ans = 1;
    for(int i = 2,r;i <= n;i = r + 1) {
        r = n / (n / i);
        (ans -= dfs(n/i) * (f1(r) - f1(i-1)) % mod) %= mod;
    }
    smd[n] = ans;
    return ans;
}


LL baoli(int n,int a,int b) {
    LL ans = 0;
    for(int i = 1;i <= n;i ++) {
        for(int j = 1;j <= i;j ++) {
            if(__gcd(i,j) == 1) {
                LL t = __gcd(ksm(i,a)-ksm(j,a),ksm(i,b)-ksm(j,b));
             //   printf("%d %d %3lld\n",i,j,t);
                ans += t;
            }
        }
    }
    return ans;
}

LL S(LL n) {
    return ni2 * (f2(n) - f1(n)) % mod;
}

LL work1(int n) {
    LL ans = 0;
    for(int i = 1,r;i <= n;i = r + 1) {
        r = n / (n / i);
        (ans += (dfs(r) - dfs(i-1)) * S(n/i) % mod) %= mod;
    }
    ans += mod; ans %= mod;
    return ans;
}


int main() {
    shai(MAXN);
    int T = read();
    while(T --) {
        int n = read(),a = read(),b = read();
        printf("%lld\n",work1(n));
    }
}

K

Meaning of the questions: There is a three-dimensional grid infinite plane, you have the right to a value of 1 on each grid point. Modifying the form of m \ (a_ {n, x_i, y_i} \) point to right point \ (V_I \) . After the second change \ (a_ {i, j, k} \) becomes \ (a_ {i + 1, j + p, k} ^ {t1} \ times a_ {i + 1, j, k + T2}} ^ {Q \ A_ Times +. 1 {I, J, K} \ A_ Times {I, J, K} \) . Seeking \ (n-\) after the second \ (a_ {0,0,0} \ bmod 998244353 \) values. \ (t1, t2, p, q, n \ le 10 ^ 9, m \ le 10 ^ 5 \)

key: Chinese remainder theorem, Theorem Lucas

Consider the contribution of each point. The equivalent of a triple (x, y, z), each minus x 1, y may be constant or decremented by a right-t1 p, z may be constant or decremented by a right-t2 q, a path weight is the right product for each step value. Q. From \ ((x, y, z ) \) went \ ((0,0,0) \) the value of all the right path and, as the value \ (v_i \) the power to multiply the answer.

In fact the weight of a path is fixed, so the question is seeking several paths. This is the \ (\ frac {n!} {A! B! C!} \) Form. That demand \ (\ frac {n!} {A! B! C!} \ Bmod (998244353 = 2 ^ {23} \ times 7 \ times 17) \)

Considered separately, crt finally merge. A7 and 17 may be directly replaced with a number of combinations of operators Lucas Theorem, consider now factorial die \ (2 ^ {23} \) how to do it. As it relates to the inverse, so that the answer should be expressed as \ (n! = A \ times 2 ^ B \) form.

\(n!=1\times 2 \times 3 \times 4 \times 5 \times ... \times n = (1 \times 3 \times 5 \times ...) \times 2^{n/2} \times (1 \times 2 \times 3 \times ... \times n/2)\)

In addition to the above it is divisible.

So we pretreated \ (. 1 \. 3 Times \ Times. 5 \ Times ... \) , this apparently on \ (2 ^ {22} \) is a circular section (as \ (2 ^ {23} +1 \ mod 2 ^ {23} = 1 \) ), so direct recursion.

7 and 17 for codes with no Lucas theorem, the same idea is used for calculation of the factorial. But here to calculate a shape such as \ (((p-1) ! \ Bmod p) ^ m \) things, according to Wilson's Theorem which always goes with the m parity-related, it can be \ (O (1) \) computing, less a log.

To read fread optimization, hdu card often. The many intermediate variables removed actually pass by, the magic ......

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

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

LL read() {
    LL n = 0;
    char a = getchar();
    bool flag = 0;
    while(a < '0' || a > '9') { 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 ksm(int a,int b,int p) {
    int ans = 1;
    while(b) {
        if(b&1) ans = 1ll * a * ans % p;
        a = 1ll * a * a % p;
        b >>= 1;
    }
    return ans;
}

int pri[] = {2,7,17};
int pk[] = {8388608,7,17};
int phi[] = {4194304,6,16};

int fac[8388608+10];
int fac7[110];
int fac17[110];

pii f[3][SZ];

const int B = 0;

void pre() {
    int p = 8388608 - 1;
    fac[0] = 1;
    fac[1] = 1;
    for(int i = 3;i <= 8388607;i += 2) {
        fac[i] = (1ll * fac[i-2] * i) & p;
        fac[i-1] = fac[i-2];
    }
    fac7[0] = 1;
    for(int i = 1;i < 7;i ++) fac7[i] = 1ll * fac7[i-1] * i % 7;
    fac17[0] = 1;
    for(int i = 1;i < 17;i ++) fac17[i] = 1ll * fac17[i-1] * i % 17;

    for(int i = 0;i < 3;i ++) {
        f[i][0].first = 1;
        for(int j = 1;j <= B;j ++) {
            int x = j,t = 0;
            while(x % pri[i] == 0) x /= pri[i],t ++;
            f[i][j].first = 1ll * f[i][j-1].first * x % pk[i];
            f[i][j].second = f[i][j-1].second + t;
        }
    }
}

pii dfs(int n,int p) {
    if(n <= B) {
        int id;
        if(p == 7) id = 1;
        else if(p == 17) id = 2;
        else id = 0;
        return f[id][n];
    }
    if(p == 7 || p == 17) {
        if(n < p) {
            return make_pair(p == 7 ? fac7[n] : fac17[n],0);
        }
        pii ans = dfs(n/p,p);
        (ans.first *= (n/p)&1 ? (p == 7 ? fac7[6] : fac17[16]) : 1) %= p;
        ans.first = ans.first * (p == 7 ? fac7[n%p] : fac17[n%p]) % p;
        ans.second += n / p;
        return ans;
    }
    else {
        if(n == 0) return make_pair(1,0);
        if(n == 1) return make_pair(1,0);
        //if(mp.count(make_pair(n,mod))) return mp[make_pair(n,mod)];
        pii ans = dfs(n >> 1,p);
        p --;
        ans.second += n >> 1;
        ans.first = (1ll * ans.first * fac[n & p]) & p;
        return ans;
    }
}

pii get_fac(int n,int p) {
    pii ans;
    if(p == 7 || p == 17) ans = dfs(n,p);
    else ans = dfs(n,8388608);
    /*int t = 1,mi = 0,mm = p == 2 ? 8388608 : p;
    for(int i = 1;i <= n;i ++) {
        int x = i;
        while(x%p==0) x/=p,mi++;
        t = 1ll * t * x % mm;
    }
    printf("%d! = %lld * %d^%lld\n",n,ans.first,p,ans.second);
    assert(t == ans.first); assert(mi == ans.second);*/
    return ans;
}

LL exgcd(LL a,LL b,LL &x,LL &y) {
    if(b == 0) {
        x = 1; y = 0;
        return a;
    }
    LL d = exgcd(b,a%b,x,y);
    LL t = x; x = y; y = t - a / b * y;
    return d;
}

LL excrt(LL *r,LL *a,int n){ // x%r=a
    LL M=a[1],R=r[1],x,y,d;
    for(int i=2;i<=n;i++){
        d=exgcd(M,a[i],x,y);
        x=(R-r[i])/d * x % a[i];
        R -= M*x;
        M = M/d * a[i];
    }
    return (R%M+M)%M;
}

int calc(int n,int a,int b,int c) {
    LL r[5],M[5];
    for(int i = 0;i < 3;i ++) {
        pii N = get_fac(n,pri[i]);
        pii A = get_fac(a,pri[i]);
        pii B = get_fac(b,pri[i]);
        pii C = get_fac(c,pri[i]);
        LL ans = 1ll * N.first
            * ksm(A.first,phi[i]-1,pk[i]) % pk[i]
            * ksm(B.first,phi[i]-1,pk[i]) % pk[i]
            * ksm(C.first,phi[i]-1,pk[i]) % pk[i];
        N.second -= A.second;
        N.second -= B.second;
        N.second -= C.second;
        ans = ans * ksm(pri[i],N.second,pk[i]) % pk[i];
        r[i+1] = ans;
        M[i+1] = pk[i];
    }
    return excrt(r,M,3);
}

struct FastIO{
  static const int S=1310720;
  int wpos,pos,len;char wbuf[S];
  FastIO():wpos(0){}
  inline int xchar(){
    static char buf[S];
    if(pos==len)pos=0,len=fread(buf,1,S,stdin);
    if(pos==len)return -1;
    return buf[pos++];
  }
  inline int xuint(){
    int c=xchar(),x=0;
    while(c<=32&&~c)c=xchar();
    if(c==-1)return -1;
    for(;'0'<=c&&c<='9';c=xchar())x=x*10+c-'0';
    return x;
  }
}io;

int main() {
  // freopen("1.in","r",stdin);
    //cout << (mod-1) / 2 / 7 * 6 / 17 * 16 << endl;
    pre();
/*
    int x;
    while(cin >> x) {
        for(int i = 0;i < 3;i ++) {
            get_fac(x,pri[i]);
        }
    }
*/
    int t1,t2,p,q,n,m;
    //while(~scanf("%d%d%d%d%d%d",&t1,&t2,&p,&q,&n,&m)) {
    while(1) {
        t1 = io.xuint();
        if(t1 == -1) break;
        t2 = io.xuint();
        p = io.xuint();
        q = io.xuint();
        n = io.xuint();
        m = io.xuint();
        LL ans = 1;
        for(int i = 1;i <= m;i ++) {
            //int x = read(),y = read(),v = read();
            //int x,y,v; scanf("%d%d%d",&x,&y,&v);
            int x = io.xuint(),y = io.xuint(),v = io.xuint();// scanf("%d%d%d",&x,&y,&v);
            if(x%p) continue;
            if(y%q) continue;
            int a = x / p,b = y / q,c = n - a - b;
            if(c<0) continue;
            int mi = calc(n,a,b,c);
            mi = 1ll * mi * ksm(t1,a,mod-1) % (mod-1) * ksm(t2,b,mod-1) % (mod-1);
        //    cout << mi << endl;
            ans = ans * ksm(v,mi,mod) % mod;
        }
        printf("%lld\n",ans);
    }
}

/**
1 1 1 1000000000 2 6
0 0 2
0 1 3
0 2 4
1 0 4
1 1 2
2 0 2

503044
*/

Guess you like

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