2019牛客暑期多校(第五场) 写题记录

A digits 2

A题 找到 数字连续出现 同时是它倍数的 n 《100 输出长度也小于100*100
//水

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

int main(){
	int n, m;
	cin >> n;
	for(int i = 1; i <= n; i++) {
		cin >> m;
		int ans =0;
		for(int j = 1; j <= m; j ++) {
			cout << m ;
		}cout << endl;
	}
    return 0;
}
B generator 1

B题 欧拉降幂死的体无全尸
我们每一位考虑 最后一位开始向前
每放入这个数 将之前的矩阵 ^ 10
就如同正常的 整数几次方 我们分开乘了
111 = (((1 * 10 ) + 1 )* 10 )+ 1;

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

struct MAT{
	int a[5][5];
	MAT (){
		memset(a, 0, sizeof a);
	}
	void init() {
		for(int i = 1; i <= 2; i ++) a[i][i] = 1;
	}
	
	friend MAT operator * (const MAT &a, const MAT &b) {
		MAT c;
		c.a[1][1] = c.a[2][2] = c.a[1][2] = c.a[2][1] = 0;
		for(int i = 1; i <= 2; i ++) for(int k = 1; k <= 2; k ++) for(int j = 1; j <= 2; j ++)
			c.a[i][j] = (1ll * c.a[i][j] + 1ll * a.a[i][k] * b.a[k][j]) % mod;
		return c;
	}
	
	friend MAT operator ^ (MAT a, long long y) {
		MAT c;
		c.init();
		for(; y; y >>= 1) {
			if(y & 1) c = c * a;
			a = a * a;
		}
		return c;
	} 
};

signed main() {
	int x0, x1, a, b;
	string s;
	cin >> x0 >> x1 >> a >> b >> s >> mod;
	MAT A; A.a[1][1] = a, A.a[1][2] = b, A.a[2][1] = 1, A.a[2][2] = 0;
	MAT B; B.a[1][1] = x1, B.a[1][2] = 0, B.a[2][1] = x0, A.a[2][2] = 0;
	for(int i = s.size() - 1; i >= 0; i --) {
		if(s[i] - '0') {
			MAT t = (A ^ (signed(s[i] - '0')));
			B = t * B;
		}
		A = (A ^ 10);
	}
	cout << B.a[2][1] << endl;
	return 0;
}
F maximum clique 1

我们要将一堆数字分开 找到集合里数字二进制1个数 相差 >= 2 最多的集合 输出

我们考虑二分图 左边 是1 个数奇数 右边偶数
这样建图 我们在同一侧的 不管肿摸组合 他们都可以
找到 < 2 之间 的 数字连边跑最大流
这样 我们二分图匹配 就能 把这些找到不要的情况
原图减去 这些 就是最大独立集合

至于输出 我们要考虑最后一次BFS depth数组 如果s能到达 就意味着 这个点并没有被和 t点一块割去
两边 同侧 而且 与之自己相连同边的 汇点 or 源点 就是 最大独立及

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5;
const int N = 1e4 + 5;
const int INF = 0x3f3f3f3f;
int a[maxn], b[maxn];
int n, m;
int head[N], depth[N], cur[N], cnt, s, t;
int to[maxn << 2], nxt[maxn << 2], cap[maxn << 2];

int resbit(int i) {
    int res = 0;
    while(i) res ++, i -= (i & -i);
    return res;
}

bool chk(int i, int j) {
    int res = 0;
    int k = i ^ j;
    while(k) res++, k-=(k & -k);
    return res < 2;
}

void ade(int a, int b, int c) {
	to[++cnt] = b, cap[cnt] = c;
	nxt[cnt] = head[a], head[a] = cnt;
}

bool bfs(){
	queue<int> que;
	que.push(s);
	memset(depth, 0, sizeof(depth));
	depth[s] = 1;
	while(!que.empty()) {
		int u = que.front(); que.pop();
		for(int i = head[u]; i != -1; i = nxt[i]) {
			if(cap[i] > 0 && depth[to[i]] == 0) {
				depth[to[i]] = depth[u] + 1;
				que.push(to[i]);
			}
		}
	}
//	for(int i = 0; i <= n + 1; i ++) {
//        cout << i << " " <<depth[i] << endl;
//    }
	if(depth[t]) return 1;
	else return 0;
}


int dfs(int u, int dist) {
	if(u == t) return dist;
	for(int &i = cur[u]; i != -1; i = nxt[i]) {
		if(depth[to[i]] == depth[u] + 1 && cap[i]) {
			int tmp = dfs(to[i], min(dist, cap[i]));
			if(tmp > 0) {
				cap[i] -= tmp;
				cap[i ^ 1] += tmp;
				return tmp;
			}
		}
	}
	return 0;
}

int dinic() {
	int res = 0, d;
	while(bfs()) {
		for(int i = 0; i < n + 5; i ++) cur[i] = head[i];
		while(d = dfs(s, INF)) res += d;
	}
	return res;
}

int main() {
    scanf("%d", &n);
    cnt = -1;
    memset(head, -1, (n + 5) * sizeof(int));
    for(int i = 1; i <= n; i ++) scanf("%d", a + i), b[i] = resbit(a[i]);

    s = 0, t = n + 1;
    for(int i = 1; i <= n; i ++) {
        if(b[i] % 2 == 1) ade(s, i, 1), ade(i, s, 0);
        else ade(i, t, 1), ade(t, i, 0);

        for(int j = i + 1; j <= n; j ++) {
            if(i == j) continue;
            if(chk(a[i], a[j])){
                if(b[i] % 2 == 1) ade(i, j, 1), ade(j, i, 0);
                else ade(j, i, 1), ade(i, j, 0);
            }
        }
    }
    int ans = dinic();

//    for(int i = 0; i <= n + 1; i ++) {
//        cout << i << " " <<depth[i] << endl;
//    }
    int f = 0;
    printf("%d\n", n - ans);
    for(int i = 1; i <= n; i ++) {
        if((b[i] % 2 == 1) ^ (depth[i] == 0)){
            if(f) cout << " ";
            cout << a[i];
            f = 1;
        }
    }cout << endl;

    return 0;
}
G subsequence 1
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 3e3 + 5;
const int mod = 998244353;
int n, m, cas;
int dp[maxn][maxn];
int f[maxn][maxn];

char s[maxn], t[maxn];

void init() {
	f[0][0] = f[1][0] = f[1][1] = 1;
	for(int i = 2; i <= 3000; i ++) {
		f[i][0] = 1;
		for(int j = 1; j <= i; j ++)
			f[i][j] = (f[i - 1][j] + f[i - 1][j - 1]) %mod;
	}
}

int main() {
	init();
	cin >> cas;
	while(cas --) {
		cin >> n >> m;
		cin >> (s + 1) >> (t + 1);
		int ans = 0;
		for(int i = 0; i <= n; i ++) dp[i][0] = 1;

		for(int i = 1; i <= n; i++)
			for(int j = 1; j <= min(m, i); j++) {
				dp[i][j] = dp[i - 1][j];
				if(s[i] == t[j]) dp[i][j] = (1ll * dp[i][j] + dp[i - 1][j - 1]) % mod;
				if(s[i] > t[j] ) {
					ans = (1ll * ans + (ll)dp[i - 1][j - 1] * f[n - i][m - j]) % mod;
				}
			}
		for(int i = 1; i <= n; i ++) {
			if(s[i] == '0') continue;
			for(int j = m; j <= n - i; j ++)
				ans = (1ll * ans + f[n - i][j]) % mod;
 		}
 		cout << ans << endl;
	}
	return 0;
}
subsequence 2

这 题是拓扑 orz
字符编号,这里每一个字符都保存一下他的位数和相对添加进来的位置就好了,
拓扑排序建边的时候建立相邻的边就好了, 如果能建 就是有解的

#include <bits/stdc++.h>
#define fastio ios::sync_with_stdio(false);cin.tie(0);
using namespace std;
typedef long long ll;
//#define int long long
const int maxn = 3e5 + 5;

int n, m, M;
int head[maxn], nums[30], deg[maxn], cnt;// 1e4 * 26 + 1e4 顶点极限
int to[maxn << 1], nxt[maxn << 1];

int getid(char s, int num) {
    return (s - 'a')*10000 + num;
}

int reid(int id) {
    return id / 10000 + 'a';
}

void ade(int a, int b) {
    to[++ cnt] = b;
    nxt[cnt] = head[a], head[a] = cnt;
}
string ans;
bool topsort() {
    ans = "";
    queue<int> que;
    for(int i = 0; i < 26; i ++) if(deg[i * 10000 + 1] == 0 && nums[i]) que.push(i * 10000 + 1);
    while(!que.empty()) {
        int x = que.front(); que.pop();
        ans.push_back(reid(x));
        for(int i = head[x]; i; i = nxt[i]) {
            int y = to[i];
            if(-- deg[y] == 0) que.push(y);
        }
    }
    return ans.size() == n;
}

signed main() {
	fastio;
	cin >> n >> m;
	M = (m - 1) * m / 2;
	string s1, s2;
	bool flag = 0;
	for(int i = 1, len; i <= M; i ++) {
        cin >> s1 >> len;
        if(len != 0) cin >> s2;
        if(flag) continue;
        int n0 = 0, n1 = 0, pre = -1, tmp;
        for(int j = 0; j < len; j ++) {
            tmp = 0;
            nums[s2[j] - 'a'] = 1;
            if(s2[j] == s1[0]) n0 ++,tmp = getid(s2[j], n0);
            else n1 ++,tmp = getid(s2[j], n1);
            if(pre != -1) {
                deg[tmp] ++;
                ade(pre, tmp);
            }
            pre = tmp;
        }
	}
	if(topsort()) cout << ans << endl;
	else cout << -1 << endl;
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值