zoukankan      html  css  js  c++  java
  • Codeforces 772C 构造 数学 + dp + exgcd

    首先我们能注意到两个数x, y (0 < x , y < m) 乘以倍数互相可达当且仅当gcd(x, m) == gcd(y, m)

    然后我们可以发现我们让gcd(x, m)从1开始出发走向它的倍数一个一个往里加元素就好啦, 往那边走

    这个可以用dp求出来, dp[ i ] 表示 gcd(x, m)从 i 开始最大元素一共有多少个, dp[ i ] = max( dp[ j ] ) + cnt[ i ]   且 i | j

    然后用扩展欧几里德求出走到下一步需要乘多少。

    #include<bits/stdc++.h>
    #define LL long long
    #define fi first
    #define se second
    #define mk make_pair
    #define PLL pair<LL, LL>
    #define PLI pair<LL, int>
    #define PII pair<int, int>
    #define SZ(x) ((int)x.size())
    #define ull unsigned long long
    
    using namespace std;
    
    const int N = 2e5 + 7;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const int mod = 1e9 + 7;
    const double eps = 1e-8;
    const double PI = acos(-1);
    
    LL n, m, dp[N], path[N];
    bool ban[N];
    vector<LL> gg[N];
    vector<LL> ans;
    vector<LL> vc;
    
    LL x, y;
    
    LL exgcd(LL a, LL b, LL &x, LL &y) {
        if(!b) {
            x = 1; y = 0;
            return a;
        } else {
            LL gcd, t; gcd = exgcd(b, a % b, x, y);
            t = x; x = y; y = t - (a / b) * y;
            return gcd;
        }
    }
    
    LL dfs(LL x) {
        if(~dp[x]) return dp[x];
        dp[x] = 0;
        for(int i = 2 * x; i < m; i += x) {
            LL cnt = dfs(i);
            if(cnt > dp[x]) {
                dp[x] = cnt;
                path[x] = i;
            }
        }
        dp[x] += SZ(gg[x]);
        return dp[x];
    }
    
    LL solve(LL pre, LL to) {
        if(pre == -1) ans.push_back(to);
        else {
            LL gcd = exgcd(pre, -m, x, y);
            if(to % gcd) exit(0);
            x *= to / gcd; y *= to / gcd;
            LL mo = abs(m / gcd);
            x = ((x % mo) + mo) % mo;
            ans.push_back(x);
        }
        return to;
    }
    
    int main() {
        memset(dp, -1, sizeof(dp));
        scanf("%lld%lld", &n, &m);
        for(int i = 1; i <= n; i++) {
            int x; scanf("%d", &x);
            ban[x] = true;
        }
        for(LL i = 1; i < m; i++) {
            if(ban[i]) continue;
            gg[__gcd(i, m)].push_back(i);
        }
        dfs(1);
        LL pre = -1;
        for(LL gcd = 1; gcd; gcd = path[gcd]) {
            for(int i = 0; i < SZ(gg[gcd]); i++)
                pre = solve(pre, gg[gcd][i]);
        }
        if(!ban[0]) ans.push_back(0);
        printf("%d
    ", SZ(ans));
        for(auto& t : ans) printf("%lld ", t);
        puts("");
        return 0;
    }
    
    /*
    */
  • 相关阅读:
    从零开始学SQLSERVER-UNION
    从零开始学SQLSERVER-BETWEEN
    从零开始学SQLSERVER-LIKE
    从零开始学SQLSERVER-存储过程(基础用法)
    从零开始学SQLSERVER-TOP
    从零开始学SQLSERER-INNER JOIN
    从零开始学SQLSERVER-DELECT(删除)
    从零开始学SQLSERVER-ORDER BY(排序)
    从零开始学SQLSERVER-WHERE
    使用 C# 9 的records作为强类型ID
  • 原文地址:https://www.cnblogs.com/CJLHY/p/10424321.html
Copyright © 2011-2022 走看看