2019nc#5

题号标题已通过代码题解/讨论通过率团队的状态
A digits 2 点击查看   1017/2384  通过
B generator 1 点击查看   567/3692  通过
C generator 2 点击查看 BSGS 38/640 未通过
D generator 3 点击查看   4/23 未通过
E independent set 1 点击查看 位元状压DP 48/115 未通过
F maximum clique 1 点击查看 二分图最大独立集 98/849 👌
G subsequence 1 点击查看 基础DP 530/2540  通过
H subsequence 2 点击查看   290/1399  通过
I three points 1 点击查看 计算几何 142/2722 未通过
J three points 2 点击查看 树DP 7/76 未通过

 

F maximum clique 1

题意

在n个数中,找出最多的子集,要求集合中任意两个数在二进制下不会出现只有一位不同。

思路

我们把只有一位数不同的点对相连。

注意到这个图是没有奇环的,所以是一个二分图,然后就是求二分图最大独立集的问题了。

学习这篇blog的思路就可以写出来

https://www.cnblogs.com/jianglangcaijin/p/6035945.html

// #pragma GCC optimize(2)
// #pragma GCC optimize(3)
// #pragma GCC optimize(4)
#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;

template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}

/**********showtime************/
            const int maxn = 5e3+9;
            int a[maxn];
            int col[maxn];
            vector<int>L, R;
            vector<int>mp[maxn];
            void dfs(int s, int c) {
                col[s] = c;
                for(int i=0; i<mp[s].size(); i++){
                    int v = mp[s][i];
                    if(col[v] == 0) dfs(v, 3 - c);
                }
            }
            int vis[maxn],match[maxn],pt[maxn];
            bool gkd(int u) {
                if(vis[u]) return false;
                vis[u] = true;
                for(int i = 0; i<mp[u].size(); i++) {
                    int v = mp[u][i];
                    if(match[v] == -1 || gkd(match[v]) ){
                        match[v] = u;
                        pt[u] = v;
                        return true;
                    }
                }
                return false;
            }
            int res[maxn];
            bool findmn(int u) {
                if(u == -1) return false;
                if(res[u]) return true;
                // res[u] = 1;
                if(col[u] == 1){
                     if(findmn(pt[u])) {res[u] = 1;return true;}
                     else return false;

                }
                else {
                    res[u] = 1;
                    for(int i=0; i<mp[u].size(); i++) {
                        int v = mp[u][i];
                        if(match[u] == v) continue;
                        findmn(v);
                    }
                    return true;
                }
            }
int main(){ 
            int n;
            scanf("%d", &n);
            for(int i=1; i<=n; i++) scanf("%d", &a[i]);
            for(int i=1; i<=n; i++) {
                for(int j=i+1; j<=n; j++) {
                    if(__builtin_popcount(a[i] ^ a[j]) == 1) {
                        mp[i].pb(j);
                        mp[j].pb(i);
                    }
                }
            }

            for(int i=1; i<=n; i++) if(col[i] == 0) dfs(i, 1);
            
            int cnt = 0;
            memset(match, -1, sizeof(match));
            for(int i=1; i<=n; i++) {
                memset(vis, 0, sizeof(vis));
                if(col[i] == 1 && gkd(i)) cnt++;  
            }

            printf("%d\n", n-cnt);
            for(int i=1; i<=n; i++) {
                if(col[i] == 2 && match[i] == -1) {findmn(i);}
            }

            vector<int>ans;
            for(int i=1; i<=n; i++) {
                if(col[i] == 1 && res[i] == 0) ans.pb(a[i]);
                if(col[i] == 2 && res[i] == 1) ans.pb(a[i]);
            }
            for(int i=0; i<ans.size(); i++) {
                printf("%d ", ans[i]);
            }
            puts("");
            return 0;
}
View Code

 

G subsequence 1

题意

给定两个数字字符串s,t。求一个数字字符串s中包含多少非连续子序列e,e在数位上大于t。

思路:

长度大于t的用组合数直接算。

等于t的我们利用动态规划dp[i][j],表示s的长度为i的前缀中有多少子序列大于t的长度为j的前缀。

// #pragma GCC optimize(2)
// #pragma GCC optimize(3)
// #pragma GCC optimize(4)
#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;

template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}

/**********showtime************/

            const int maxn = 3e3+9;
            char s[maxn],t[maxn];
            ll f[maxn][maxn];
            ll C (int n, int m) {
                if(m > n) return 0;
                if(f[n][m]) return f[n][m];
                if(m == 0||m == n) return f[n][m] = 1;
                return f[n][m] = (C(n-1, m-1) + C(n-1,m) ) %mod;
            }
            ll dp[maxn][maxn];
int main(){
            int T;  scanf("%d", &T);
            while(T--) {
                int n,m;
                scanf("%d%d", &n, &m);
                scanf("%s%s", s + 1, t + 1);
                ll ans = 0;
                for(int i=1; i<=n; i++) {
                    if(s[i] == '0') continue;
                    int yu = n - i;
                    for(int j = m; j<=yu; j++) 
                        ans = (ans + C(yu, j)) % mod;
                }

                for(int i=0; i<=n; i++) dp[i][0] = 1;
                for(int i=1; i<=n; i++) {   
                    for(int j=1; j<=m; j++) {
                        dp[i][j] = dp[i-1][j];
                        if(s[i] == t[j]) {
                            dp[i][j] = (dp[i-1][j-1] + dp[i][j])% mod;
                        }
                        else if(s[i] > t[j]) {
                            ans = (ans + dp[i-1][j-1] * C(n-i , m-j) % mod)% mod;
                        }
                    }
                }
                printf("%lld\n", ans);
                for(int i=0; i<=n; i++){
                    for(int j=0; j<=m; j++) 
                        dp[i][j] = 0;
                }
            }
            return 0;
}
View Code

 

posted @ 2019-08-01 22:00  ckxkexing  阅读(255)  评论(0编辑  收藏  举报