2019頭の牛のオフより学校第5の問題点の解決策

2019頭の牛のオフより学校第5の問題点の解決策

トピックリンク

A.digits 2

出力\(N- \)\(N- \)することができます。


コード

#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

小数高速電力、\(A ^ N- =(A ^ 2)^ {\ {2} {N-} FRAC} \)するように操作(\ A ^ N =(A ^ {10})^(\ FRAC {N} {10})\)は、単独でそれを取るために残りすることができます。
コードを参照してください。


コード

#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アルゴリズム\(X_I = ax_ {I- 1} + B \ MOD P \) の総称求め、\(x_nに関する= A ^ nx_0 + \ FRAC {B(1-A ^ N-)を。 。1-A} {} \) 要求の対象ので\(X_I = V \ MOD P \) 我々はすべてう\(A_N \)式の右辺に独立に与える:\(N-A ^ = \ FRAC Vの+ {\ FRAC {B} {} {}。1 A-X_0 + \ FRAC {B} {}}。1-A MOD P \ \)
BSGSによると、私たちはスローされます\(^ A jは\)を直接列挙するために、ハッシュテーブルの内部に配置され、すべての前右部に右に左に見つけること。この質問を尋ねるには、より多数で、T.を指示するのは簡単ですので、
事前に行われると考えることができ、その後、私たちはします\(\ N-)のように書くこと(i *はT + J、T = \ lceil \ SQRT(P)\ rceil \)\ フォーム、その後、\(A ^ {それ} \)はるかに高速になり、問い合わせ、前右、左、前処理の逆に乗って。
私がします謎の場所があります\(N \)として扱われ(私はTJ \ *)\ ...の形で96で立ち往生されています\は(私はT + J \ *)の前に。私は、どのような状況を知りません。
コードは以下の通りであります:


コード

#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は1セット

成形圧力\(DP \) +バックパック、被験者はサブセットを求めているからです。その空間は、限られているので注意してください\(DP \) char型の配列。
コードは以下の通りであります:


コード

#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;
}

最大1回のクリック

質問の最大のグループは、ビットは、最大の独立したセットを求めて検討し、質問を変換します。
任意の2点間の最大のグループであり、\(「ビット\) それは任意の2点間の補グラフであり、1以上によって異なる\(」ビット\)差が1に等しい(任意の二つの数字は等しくありません)。その構造の相補体は、二部グラフである見つけることは容易です。すべての左仮定\(ビット\)ポイントの奇数、右は\(ビット\)ポイントの偶数は、次いで、ライン上のネットワーク・フローを実行します。
ここでは、出力プログラムノートでは、クレジットBFSの使用は最後の時間になると、その後、BFSもちろん手で遊ぶ、あなたが知っている理由は、この出力は、左のマークされていないDFS点から二部グラフの性質と方法は同じです。上の左のマークされていない点から、その後、右のマーカーを訪問し、反史上側を左にマークし、繰り返されたリサイクルポイントをBFS。だから、最終的には正しい場所にマークされていない左とポイントが答え、ライン上のこれらの点を除去するための最大の独立集合の最小点で覆われているマーク。
コードは以下の通りであります:


コード

#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

多数の追加の数よりも大きい、またはそれはビットの数よりも大きい、またはその同等の長さよりも少し大きくなっています。だから、これに応じて彼のラインを実行します。
列挙は、出発点と(あなたが先行ゼロを持つことができないため)、後の数を選択します。場合は、より良い取引の中央値よりも大きく、いくつかの問題の組み合わせがあります。
等しい場合(DP \)を\はプログラム同じセットの数と一致する\(DP(i、j)は \) 文字列を表す(私は\)\うち選択された、ビットを\(J \)を可能番目第二文字列の前に\(J \)プログラムの数などの相。その後、次の大小関係に応じて転送され、計算されます。


コード

#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

関係の大きさを決定するために、各2、そして最終的には関係の大きさを知ること、トポロジが彼のために行っていると考えられます。
メインは、それが望んでいるコードの詳細を確認することです。


コード

#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;
}

おすすめ

転載: www.cnblogs.com/heyuhhh/p/11297785.html