2019 cattle off more school fifth problem solution

2019 cattle off more school fifth problem solution

Topic Link

A.digits 2

Output \ (n-\) a \ (n-\) can.


Code

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

int main() {
    ios::sync_with_stdio(false); cin.tie(0);
    int T;
    cin >> T;
    while(T--) {
        int n; cin >> n;
    }
    return 0;
}

B.generator 1

Decimal fast power, \ (A ^ n-= (A ^ 2) ^ {\ FRAC {n-} {2}} \) engineered to \ (a ^ n = (a ^ {10}) ^ (\ frac {n} {10}) \) can be, the remainder to take it alone.
Refer to code:


Code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 3, MAX = 1e6 + 15;
ll a, b, x0, x1, MOD;
char s[MAX];
struct matrix{
    int A[N][N];
    int n,m;
    matrix(){memset(A,0,sizeof(A));}
};
int add(ll x, ll y) {
    x += y;
    if(x >= MOD) x -= MOD;
    return x;
}
int mul(ll x, ll y) {
    return (x *= y) >= MOD ? x % MOD : x;
}
matrix operator * (const matrix &a,const matrix &b){
    matrix ans;
    ans.n=a.n;ans.m=b.m;
    for(int i=1;i<=ans.n;i++)
        for(int j=1;j<=ans.m;j++)
            for(int k=1;k<=b.n;k++)
                ans.A[i][j] = add(ans.A[i][j], mul(a.A[i][k], b.A[k][j])) ;
    return ans ;
}
matrix operator + (const matrix &a,const matrix &b){
    matrix ans;
    ans.n=a.n;ans.m=a.m;
    for(int i=1;i<=ans.n;i++){
        for(int j=1;j<=ans.m;j++){
            ans.A[i][j]=(a.A[i][j]+b.A[i][j])%MOD;
        }
    }
    return ans ;
}
matrix qp_Mat(matrix a,ll b){
    matrix ans;
    ans.n=ans.m=a.n;
    for(int i=1;i<=ans.n;i++) ans.A[i][i]=1;
    while(b){
        if(b&1) ans=ans*a;
        a=a*a;
        b>>=1;
    }
    return ans ;
}
int main() {
    scanf("%lld%lld%lld%lld", &x0, &x1, &a, &b);
    scanf("%s", s);
    scanf("%lld", &MOD);
    matrix trans;
    trans.n = trans.m = 2;
    trans.A[2][1] = 1; trans.A[1][2] = b; trans.A[2][2] = a;
    matrix ans; ans.n = ans.m = 2;
    ans.A[1][1] = ans.A[2][2] = 1;
    int last = strlen(s) - 1;
    while(last >= 0) {
        if(s[last] != '0') {
            int now = s[last] - '0';
            ans = ans * qp_Mat(trans, now);
        }
        trans = qp_Mat(trans, 10);
        last--;
    }
    matrix A; A.n = 1, A.m = 2;
    A.A[1][1] = x0, A.A[1][2] = x1;
    A = A * ans;
    cout << A.A[1][1] << endl;
    return 0;
}

C.generator 2

BSGS algorithm for the subject given \ (x_i = ax_ {I-. 1} + B \ MOD P \) , seeking the general term of: \ (x_n = A ^ nx_0 + \ FRAC {B (. 1-A ^ n-) . 1-a} {} \) , since the subject of the request \ (x_i = V \ MOD P \) , we will all \ (A_N \) independent on the right side of the equation to give: \ (n-a ^ = \ FRAC V + {\ FRAC {B} {} {}. 1 A-x_0 + \ FRAC {B} {}}. 1-A \ MOD P \) .
According to BSGS, we will throw a \ (a ^ j \) to the right to every pre-right part, placed inside the hash table for direct enumeration left to find. In asking this question because more in number, it is easy to direct T.
Can be considered to be pre-made, then we will \ (n-\) be written as (i * t + j, t = \ lceil \ sqrt (p) \ rceil \) \ form, then \ (a ^ { it} \) the inverse ride on the right, left pretreatment before the inquiry, which would be much faster.
There is a mystery place that I will \ (n \) treated as \ (i * tj \) has been stuck at 96 in the form of ... \ (i * t + J \) before. . . do not know what is happening.
code show as below:


Code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct B{
    const int mod = 524287; // (1 << 19) - 1;
    int tot;
    int h[524288], next[524288], L[524288], v[524288];
    int Find(ll x) {
        int k = h[x & mod];
        while(k != 0) {
            if(L[k] == x) return v[k];
            else k = next[k];
        }
        return -1;
    }
    void Add(int e, int i) {
        tot++;
        next[tot] = h[e & mod];
        L[tot] = e; v[tot] = i;
        h[e & mod] = tot;
    }
    void init(int a, int n) {
        memset(h, 0, sizeof(h)); memset(L, 0, sizeof(L));tot = 0;
        memset(next, 0, sizeof(next)); memset(v, 0, sizeof(v));
        ll t, e = 1;
        t = (int)sqrt(n) + 1;
        for(int i = 0; i < t; i++) {
            if(Find(e) == -1) Add(e, i);
            e = e * a % n;
        }
    }
    ll BSGS(int a, int b, int n, ll v, ll t) { // a ^ x = b (mod n)
        for(int i = 0; i < t; i++) {
            if(Find(b) != -1) return i * t + Find(b);
            b = b * v % n;
        }
        return -1;
    }
}S;
int p;
ll qp(ll a, ll b) {
    ll ans = 1;
    while(b) {
        if(b & 1) ans = ans * a % p;
        a = a * a % p;
        b >>= 1;
    }
    return ans;
}
ll n;
int x0, a, b, T, q;
int main() {
    ios::sync_with_stdio(false); cin.tie(0);
    cin >> T;
    while(T--) {
        cin >> n >> x0 >> a >> b >> p;
        if(a == 0) {
            cin >> q;
            while(q--) {
                int v; cin >> v;
                if(x0 == v) cout << 0 << '\n';
                else if(b == v) cout << 1 << '\n';
                else cout << -1 << '\n';
            }
            continue;
        }
        if(a == 1) {
            cin >> q; ll tmp = qp(b, p - 2);
            while(q--) {
                int v; cin >> v;
                int ans = 1ll * (v - x0 + p) % p * tmp % p;
                if(ans >= n) cout << -1 << '\n';
                else cout << ans << '\n';
            }
            continue;
        }
        int c = 1ll * b * qp(a - 1, p - 2) % p;
        int t = (int)sqrt(p) + 1;
        S.init(a, p);
        cin >> q;
        while(q--) {
            int v; cin >> v;
            ll x = v + c, y = x0 + c;
            if(y % p == 0) {
                if(x % p == 0) cout << 0 << '\n';
                else cout << -1 << '\n';
                continue ;
            }
            ll z = x * qp(y, p - 2) % p;
            int k = qp(qp(a, t), p - 2);
            ll ans = S.BSGS(a, z, p, k, t);
            if(ans == -1 || ans >= n) cout << -1 << '\n';
            else cout << ans << '\n';
        }
    }
    return 0;
}

E.independent set 1

Shaped pressure \ (DP \) + backpack, because the subject is seeking the subset. Note that space is limited, so the \ (dp \) array of char type.
code show as below:


Code

#include <bits/stdc++.h>
using namespace std;
const int N = 26;
char dp[1 << N];
int e[N];
int n, m;
int Max(char x, char y) {
    return x > y ? x : y;
}
int main() {
    ios::sync_with_stdio(false); cin.tie(0);
    cin >> n >> m;
    for(int i = 1; i <= m; i++) {
        int u, v; cin >> u >> v;
        e[u] |= (1 << v);
        e[v] |= (1 << u);
    }
    for(int i = 0; i < n; i++) {
        e[i] ^= (1 << i);
        e[i] = ~e[i];
    }
    int ans = 0;
    for(int i = 1; i < (1 << n); i++) {
        int lb = __builtin_ffs(i) - 1;
        dp[i] = Max(dp[i ^ (1 << lb)], dp[i & e[lb]] + 1);
        ans += dp[i];
    }
    cout << ans;
    return 0;
}

maximum 1 click

The largest group of questions asked, convert the question a bit, consider seeking maximum independent set.
Between any two points is the largest group \ ( 'bit \) differ by more than 1, then it is the complement graph between any two points \ (' bit \) of the difference is equal to 1 (any two numbers are not equal). Complements of its construction is easy to find out which is a bipartite graph. Assume all left \ (bit \) an odd number of points, then the right is the \ (bit \) an even number of points, and then run a network flow on the line.
When the output program note here is the use of credit bfs last time, and then play with the hand bfs course, you know why this output, the nature and methods of bipartite graph from left unmarked dfs point is the same: from left unmarked point on, and then visit the right marker, bfs recycling point anti-ever mark left side, and has been repeated. . . So finally left unmarked on the right spot and mark the point is covered by the minimum point of the answer, the largest independent set to remove these points on the line.
code show as below:


Code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 5005;
int n;
int a[N];
#define INF 0x3f3f3f3f
template <class T>
struct Dinic{
    struct Edge{
        int v, next;
        T flow;
        Edge(){}
        Edge(int v, int next, T flow) : v(v), next(next), flow(flow) {}
    }e[5 * 1000000];
    int head[N], cur[N], tot;
    int dep[N];
    void init() {
        memset(head, -1, sizeof(head)); tot = 0;
    }
    void adde(int u, int v, T w, T rw = 0) {
        e[tot] = Edge(v, head[u], w);
        head[u] = tot++;
        e[tot] = Edge(u, head[v], rw);
        head[v] = tot++;
    }
    bool BFS(int _S, int _T) {
        memset(dep, -1, sizeof(dep));
        queue <int> q; q.push(_S); dep[_S] = 0;
        while(!q.empty()) {
            int u = q.front(); q.pop();
            for(int i = head[u]; ~i; i = e[i].next) {
                int v = e[i].v;
                if(dep[v] == -1 && e[i].flow > 0) {
                    dep[v] = dep[u] + 1;
                    q.push(v);
                }
            }
        }
        return dep[_T] != -1;
    }
    T dfs(int _S, int _T, T a) {
        T flow = 0, f;
        if(_S == _T || a == 0) return a;
        for(int i = head[_S]; ~i; i = e[i].next) {
            int v = e[i].v;
            if(dep[v] != dep[_S] + 1) continue;
            f = dfs(v, _T, min(a, e[i].flow));
            if(f) {
                e[i].flow -= f;
                e[i ^ 1].flow += f;
                flow += f;
                a -= f;
                if(a == 0) break;
            }
        }
        if(!flow) dep[_S] = -1;
        return flow;
    }
    T dinic(int _S, int _T) {
        T max_flow = 0;
        while(BFS(_S, _T)) {
            max_flow += dfs(_S, _T, INF);
        }

        return max_flow;
    }
};
bool is_source[N];
Dinic <int> D;
bool ok(int x) {
    return x && ((x & (x - 1)) == 0);
}
int main() {
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
        if(__builtin_popcount(a[i]) & 1) is_source[i] = 1;
    }
    D.init();
    for(int i = 1; i <= n; i++) {
        if(is_source[i]) D.adde(0, i, 1);
        else D.adde(i, n + 1, 1);
    }
    for(int i = 1; i <= n; i++) {
        for(int j = i + 1; j <= n; j++) {
            if(ok(a[i] ^ a[j])) {
                if(is_source[i]) D.adde(i, j, 1);
                else D.adde(j, i, 1);
            }
        }
    }
    int ans = n - D.dinic(0, n + 1);
    printf("%d\n", ans);
    vector <int> res;
    for(int i = 1; i <= n; i++) {
        if(is_source[i]) {
            if(D.dep[i] != -1) res.push_back(a[i]);
        } else {
            if(D.dep[i] == -1) res.push_back(a[i]);
        }
    }
    int SZ = res.size();
    for(int i = 0; i < SZ; i++) {
        printf("%d%c", res[i], " \n"[i == SZ - 1]);
    }
    return 0;
}

G.subsequence 1

A number greater than a number of additional, or it is greater than the number of bits, or a bit larger than its equal length. So according to this carry out his line.
The case is greater than the median of the better deal is a combination of several problems: enumeration starting point and then later choose a number (because you can not have leading zeros).
Case equal to \ (DP \) matches the number of programs equal set \ (dp (i, j) \) represents a string to \ (I \) bits, selected out \ (J \) th capable and before the second string \ (J \) phase like the number of programs. Then transferred and calculated according to the size relationship between the next.


Code

#include<bits/stdc++.h>
typedef long long ll;
const int MAXN = 3e3 + 5, N = 3e3, MAXM = 3e5 + 5, INF = 0x3f3f3f3f, MOD = 998244353;
const ll INFL = 0x3f3f3f3f3f3f3f3f;
using namespace std;
const int oo = (1e9) - (1e6);
#define lson o<<1,l,m
#define rson o<<1|1,m+1,r
#define mid l + ((r-l)>>1)
#define pb push_back
#define RR register
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define all(v) (v.begin(),v.end())
#define lc(x) c[x][0]
#define rc(x) c[x][1]
#define R register int
typedef long double db;
typedef unsigned int uint;
#define G c=getchar()
 
int t, n, m, dp[MAXN][MAXN];
char s1[MAXN], s2[MAXN];
ll fact[MAXN], ifact[MAXN], sum[MAXN][MAXN];
inline void add(int &x, int y) {
    x += y;
    if (x >= MOD)x -= MOD;
}
inline ll C(int n, int m) {
    if (m > n)return 0;
    return fact[n] * ifact[n - m] % MOD*ifact[m] % MOD;
}
ll qpow(ll a, ll b) {
    ll ans = 1;
    for (; b; b >>= 1, a = a * a%MOD)if (b & 1)ans = ans * a%MOD;
    return ans;
}
void init() {
    fact[0] = fact[1] = 1;
    for (int i = 2; i <= N; i++)fact[i] = fact[i - 1] * i%MOD;
    ifact[N] = qpow(fact[N], MOD - 2);
    for (int i = N - 1; i >= 0; i--)ifact[i] = ifact[i + 1] * (i + 1) % MOD;
    for (int i = 1; i <= N; i++) {
        sum[i][0] = 1;
        for (int j = 1; j <= i; j++) {
            sum[i][j] = (sum[i][j - 1] + C(i, j)) % MOD;
            assert(sum[i][j] >= 0);
        }
    }
}
int main() {
    ios::sync_with_stdio(false); cin.tie(0);
    init();
    cin >> t;
    while (t--) {
        cin >> n >> m;
        cin >> (s1 + 1) >> (s2 + 1);
        for (int i = 0; i <= n; i++)
            for (int j = 0; j <= n; j++)dp[i][j] = 0;
        dp[0][0] = 1;
        for (int i = 1; i <= n; i++) {
            dp[i][0] = 1;
            for (int j = 1; j <= min(i, m); j++) {
                dp[i][j] = dp[i - 1][j];
                if (s2[j] != s1[i])continue;
                add(dp[i][j], dp[i - 1][j - 1]);
            }
        }
        int ans = 0;
        for (int i = 1; i <= n; i++) {
            if (s1[i] != '0' && n - i >= m) {
                add(ans, (sum[n - i][n - i] - sum[n - i][m - 1] + MOD) % MOD);
            }
            for (int j = 1; j <= min(i, m); j++) {
                if (s1[i] <= s2[j])continue;
                add(ans, dp[i - 1][j - 1] * C(n - i, m - j) % MOD);
            }
        }
        cout << ans << '\n';
    }
    return 0;
}

H.subsequence 2

Knowing the size of the relationship between each two, and finally to determine the size of a relationship, so it is conceivable that the topology carry out his order.
The main is to look at the details of the code it wants.


Code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e4 + 5, M = 1e6 + 5;
int n, m, cnt;
vector <int> g[26];
string str;
struct Edge {
    int v, next;
}e[M << 1];
int head[N], tot;
char mp[N], ans[N];
void adde(int u, int v) {
    e[tot].v = v; e[tot].next = head[u]; head[u] = tot++;
}
int in[N], num[26];
int main() {
    scanf("%d%d", &n, &m);
    memset(num, -1, sizeof(num));
    memset(head, -1, sizeof(head));
    int flag = 0;
    for (int i = 1; i <= m * (m - 1) / 2; i++) {
        char s[10]; scanf("%s", s);
        int len; scanf("%d", &len); getchar();
        getline(cin, str);
        if (cnt > n) {    //之前没这个一直RE
            flag = 1;
            continue;
        }
        int cnt1 = 0, cnt2 = 0;
        for (int j = 0; j < len; j++) {
            if (str[j] == s[0]) cnt1++;
            else cnt2++;
        }
        int t1 = s[0] - 'a', t2 = s[1] - 'a';
        if (num[t1] == -1) {
            num[t1] = cnt1;
            while (cnt1--) g[t1].push_back(++cnt), mp[cnt] = s[0];
        }
        else {
            if (num[t1] != cnt1) flag = 1;
        }
        if (num[t2] == -1) {
            num[t2] = cnt2;
            while (cnt2--) g[t2].push_back(++cnt), mp[cnt] = s[1];
        }
        else {
            if (num[t2] != cnt2) flag = 1;
        }
        if (flag) continue;
        int p1 = 0, p2 = 0;
        for (int j = 0; j < len - 1; j++) {
            if (str[j] == s[0]) {
                if (str[j + 1] == s[0]) {
                    adde(g[t1][p1], g[t1][p1 + 1]);
                    in[g[t1][p1 + 1]]++;
                }
                else {
                    adde(g[t1][p1], g[t2][p2]);
                    in[g[t2][p2]]++;
                }
                p1++;
            }
            else {
                if (str[j + 1] == s[0]) {
                    adde(g[t2][p2], g[t1][p1]);
                    in[g[t1][p1]]++;
                }
                else {
                    adde(g[t2][p2], g[t2][p2 + 1]);
                    in[g[t2][p2 + 1]]++;
                }
                p2++;
            }
        }
    }
    if (cnt != n || flag) {
        cout << -1;
        return 0;
    }
    int tmp = 0;
    queue <int > q;
    for (int i = 1; i <= cnt; i++) if (!in[i]) q.push(i);
    while (!q.empty()) {
        if ((int)q.size() > 1) { //严格拓扑序,那么队列中只有一个
            cout << -1;
            return 0;
        }
        int u = q.front(); q.pop();
        ans[++tmp] = mp[u];
        int k = 0;
        for (int i = head[u]; i != -1; i = e[i].next) {
            int v = e[i].v;
            if (--in[v] == 0) q.push(v), k++;
        }
    }
    if (tmp != n) {
        cout << -1;
        return 0;
    }
    for (int i = 1; i <= tmp; i++) cout << ans[i];
    return 0;
}

Guess you like

Origin www.cnblogs.com/heyuhhh/p/11297785.html