2018-2019 ICPC, NEERC, Northern Eurasia Finals 7/13

A

Solved: 03:26(zkp)
zkp今天的锅有点大啊。。开场上来打A,然后2h后说完蛋了。
看完题扔给他了一个DP打表写法
他写完之后说TN^2怎么过啊
嗯??不是打表吗?
-7
太dirt了

#include <bits/stdc++.h>
using namespace std;
int dp[4][4][500][500];
vector<pair<int,int> >r[4][4][500][500];
int main() {
	for(int i=0;i<3;i++)for(int j=0;j<3;j++)for(int k=0;k<=200;k++)for(int l=0;l<=200;l++)dp[i][j][k][l]=0;
	dp[0][0][0][0]=1;
	for(int i=0;i<3;i++)for(int j=0;j<3&&i+j<=4;j++)
	{
		for(int k=0;k<=200;k++)for(int l=0;l<=200;l++)if(dp[i][j][k][l])
		{
			for(int m=0;m+k<=200;m++)
				if(i+j<4)
				{
					int n=0;
					if(m<23)dp[i][j+1][m+k][l+25]=true,r[i][j+1][m+k][l+25]=r[i][j][k][l],
						r[i][j+1][m+k][l+25].push_back(make_pair(m,25));
					if(m>=25)dp[i+1][j][m+k][l+m-2]=true,r[i+1][j][m+k][l+m-2]=r[i][j][k][l],
						r[i+1][j][m+k][l+m-2].push_back(make_pair(m,m-2));
					if(m>=23)dp[i][j+1][m+k][l+m+2]=true,r[i][j+1][m+k][l+m+2]=r[i][j][k][l],
						r[i][j+1][m+k][l+m+2].push_back(make_pair(m,m+2));
					if(m==25)for(int n=0;n<=23;n++)dp[i+1][j][m+k][l+n]=true,
						r[i+1][j][m+k][l+n]=r[i][j][k][l],
						r[i+1][j][m+k][l+n].push_back(make_pair(m,n));
				}
				else
				{
					int n=0;
					if(m<13)dp[i][j+1][m+k][l+15]=true,r[i][j+1][m+k][l+15]=r[i][j][k][l],
						r[i][j+1][m+k][l+15].push_back(make_pair(m,15));
					if(m>=15)dp[i+1][j][m+k][l+m-2]=true,r[i+1][j][m+k][l+m-2]=r[i][j][k][l],
						r[i+1][j][m+k][l+m-2].push_back(make_pair(m,m-2));
					if(m>=13)dp[i][j+1][m+k][l+m+2]=true,r[i][j+1][m+k][l+m+2]=r[i][j][k][l],
						r[i][j+1][m+k][l+m+2].push_back(make_pair(m,m+2));
					if(m==15)for(int n=0;n<=13;n++)dp[i+1][j][m+k][l+n]=true,
						r[i+1][j][m+k][l+n]=r[i][j][k][l],
						r[i+1][j][m+k][l+n].push_back(make_pair(m,n));
				}
		}
	}
	int t;
	cin>>t;
	while(t--)
	{
		int a,b;
		bool w=true;
		cin>>a>>b;
		if(dp[3][0][a][b])
		{
			cout<<"3:0"<<endl;
			for(int i=0;i<r[3][0][a][b].size();i++)
				cout<<r[3][0][a][b][i].first<<":"<<r[3][0][a][b][i].second<<" ";
			cout<<endl;
		}
		else if(dp[3][1][a][b])
		{
			cout<<"3:1"<<endl;
			for(int i=0;i<r[3][1][a][b].size();i++)
				cout<<r[3][1][a][b][i].first<<":"<<r[3][1][a][b][i].second<<" ";
			cout<<endl;
		}
		else if(dp[3][2][a][b])
		{
			cout<<"3:2"<<endl;
			for(int i=0;i<r[3][2][a][b].size();i++)
				cout<<r[3][2][a][b][i].first<<":"<<r[3][2][a][b][i].second<<" ";
			cout<<endl;
		}
		else if(dp[2][3][a][b])
		{
			cout<<"2:3"<<endl;
			for(int i=0;i<r[2][3][a][b].size();i++)
				cout<<r[2][3][a][b][i].first<<":"<<r[2][3][a][b][i].second<<" ";
			cout<<endl;
		}
		else if(dp[1][3][a][b])
		{
			cout<<"1:3"<<endl;
			for(int i=0;i<r[1][3][a][b].size();i++)
				cout<<r[1][3][a][b][i].first<<":"<<r[1][3][a][b][i].second<<" ";
			cout<<endl;
		}
		else if(dp[0][3][a][b])
		{
			cout<<"0:3"<<endl;
			for(int i=0;i<r[0][3][a][b].size();i++)
				cout<<r[0][3][a][b][i].first<<":"<<r[0][3][a][b][i].second<<" ";
			cout<<endl;
		}
		else cout<<"Impossible"<<endl;
	}
	return 0;
}

B

Unsolved

C

Unsolved

D

Unsolved

E

Solved: 02:01 (HOOCCOOH)

#include <iostream>
#include <cassert>
#include <algorithm>
#include <utility>
#include <vector>

auto make_route(int n) {
    auto v = std::vector<std::pair<int, int>>();
    auto row = [&](int x, int from, int to, int cnt) {
        v.emplace_back(x, from);
        cnt -= 2;
        for(int i = 0; i < 8 && cnt > 0; ++i)
            if(i != from && i != to) {
                v.emplace_back(x, i);
                --cnt;
            }
        v.emplace_back(x, to);
    };

    int from = 0;
    for(int i = 0; ; ++i)
        if(n <= 2)
            assert(false);
        else if(n <= 9) {
            int to = i == 7 ? 6 : 7;
            row(i, from, to, n - 1);
            v.emplace_back(7, 7);
            break;
        } else if(n == 10) {
            row(i, from, 6, 8);
            v.emplace_back(7, 6);
            v.emplace_back(7, 7);
            break;
        } else {
            row(i, from, from ^ 1, 8);
            from ^= 1;
            n -= 8;
        }

    return v;
}


int main() {
    std::ios::sync_with_stdio(false);

    int n;
    std::cin >> n;
    auto steps = make_route(n + 1);
    // std::cerr << "<" << steps.size() << ">\n";
    for(auto &c: steps)
        std::cout
            << (char)('a' + c.second) << c.first + 1
            << ' ';
    std::cout << std::endl;

    return 0;
}

F

Solved: 01:21 (BPM136)
可以转化为 ∑ i = 1 k a i ∗ k i = n − 1 \sum_{i=1}^{k} a_i*k_i=n-1 i=1kaiki=n1
这东西非常不好解
发现这是k元不定方程非常不好解,如果n是一个prime,那么感觉是无解的
否则一定存在一种拆分方案,使得两个因子互素
那么用那两个因子来计算的不定方程一定有解,exgcd即可

#include <bits/stdc++.h>

using namespace std;

#define int long long

int ExGcd(int a, int b, int& x, int& y) {
	if (b == 0) 
		return x = 1, y = 0, a;
	int d = ExGcd(b, a % b, x, y);
	int z = x;
	x = y;
	y = z - y * (a / b);
	return d;
}

#undef int

int main() {

#define int long long
	int n;
	cin >> n;
	for (int i = 2; i * i <= n; ++i) 
		if (n % i == 0) {
			int a = i, b = n / i;
			int x, y;
			int d = ExGcd(a, b, x, y);
			if ((n - 1) % d) 
				continue;
			x = (x + b / d) * ((n - 1) / d);
			x = (x % (b / d) + b / d) % (b / d);
			y = (n - 1 - a * x) / b;
			puts("YES");
			puts("2");
			cout << x << ' ' << b << '\n';
			cout << y << ' ' << a << '\n';
			return 0;
		}
	puts("NO");
}

G

Solved: 00:32 (BPM136)
对于手残的我不那么温暖的签到然而+了

#include <bits/stdc++.h>

using namespace std;

using ll = long long;

int a[100];

int main() {
	ios::sync_with_stdio(0);
	int T;
	cin >> T;
	while (T--) {
		int n;
		cin >> n;
		for (int i = 0; i < 7; ++i) {
			cin >> a[i];
			a[i + 7] = a[i];
		}
		int sum = 0;
		for (int i = 0; i < 7; ++i)
			sum += a[i];
		int ans = 1e9;
		for (int i = 0; i < 7; ++i) {
			if (n < sum) {
				int t = 0;
				for (int j = i; j < i + 7; ++j) {
					t += a[j];
					if (t == n) {
						ans = min(ans, j - i + 1);
						break;
					}
				}
			} else {
				int t = 0;
				if (n - (n - 1) / sum * sum == 0) {
					ans = min(ans, 7 * ((n - 1) / sum));
					continue;
				}
				for (int j = i; j < i + 7; ++j) {
					t += a[j];
					if (t == (n - (n - 1) / sum * sum)) {
						ans = min(ans, 7 * ((n - 1) / sum) + j - i + 1);
						break;
					}
				}
			}
		}
		cout << ans << '\n';
	}
}


H

Unsolved

I

Unsolved

J

Unsolved

K

Solved: 02:13 (BPM136)
即维护l到r区间每个元+i的最大值
就是sum[l][r]+l在r固定时的最大值

#include <bits/stdc++.h>

using namespace std;

int const MAXB = 1000000;
int const n = 1000000;
int const N = 1000000;

using ll = long long;

ll bit[N];

void BITAdd(int x, int y) {
	while (x <= MAXB) {
		bit[x] += y;
		x += x & -x;
	}
}

ll BITQuery(int x) {
	ll ret = 0;
	while (x) {
		ret += bit[x];
		x -= x & -x;
	}
	return ret;
}


ll mx[N << 2], lz[N << 2];

void pushup(int k) {
	mx[k] = max(mx[k << 1], mx[k << 1 | 1]);
}

void pushdown(int k) {
	mx[k << 1] += lz[k];
	mx[k << 1 | 1] += lz[k];
	lz[k << 1] += lz[k];
	lz[k << 1 | 1] += lz[k];
	lz[k] = 0;
}

void SegBuild(int k, int l, int r) {
	if (l == r) {
		lz[k] = 0;
		mx[k] = l;
		return;
	}
	int mid = (l + r) >> 1;
	SegBuild(k << 1, l, mid);
	SegBuild(k << 1 | 1, mid + 1, r);
	pushup(k);
}

void SegAdd(int k, int l, int r, int _l, int _r, int val) {
	if (l == _l && r == _r) {
		lz[k] += val;
		mx[k] += val;
		return;
	}
	int mid = (l + r) >> 1;
	if (lz[k]) 
		pushdown(k);
	if (_r <= mid)
		SegAdd(k << 1, l, mid, _l, _r, val);
	else if (_l > mid)
		SegAdd(k << 1 | 1, mid + 1, r, _l, _r, val);
	else 
		SegAdd(k << 1, l, mid, _l, mid, val),
		SegAdd(k << 1 | 1, mid + 1, r, mid + 1, _r, val);
	pushup(k);
}

ll SegQuery(int k, int l, int r, int _l, int _r) {
	if (l == _l && r == _r) 
		return mx[k];
	int mid = (l + r) >> 1;
	if (lz[k])
		pushdown(k);
	ll ret;
	if (_r <= mid)
		ret = SegQuery(k << 1, l, mid, _l, _r);
	else if (_l > mid)
		ret = SegQuery(k << 1 | 1, mid + 1, r, _l, _r);
	else {
		ll retx = SegQuery(k << 1, l, mid, _l, mid);
		ll rety = SegQuery(k << 1 | 1, mid + 1, r, mid + 1, _r);
		ret = max(retx, rety);
	}
	pushup(k);
	return ret;
}

int t[N], d[N];

int main() {
	ios::sync_with_stdio(0);
	SegBuild(1, 1, n);
	int T;
	cin >> T;
	char op;
	for (int i = 1; i <= T; ++i) {
		cin >> op;
		if (op == '+') {
			cin >> t[i] >> d[i];
			SegAdd(1, 1, n, 1, t[i], d[i]);
			BITAdd(t[i], d[i]);
		}
		if (op == '-') {
			int x;
			cin >> x;
			SegAdd(1, 1, n, 1, t[x], -d[x]);
			BITAdd(t[x], -d[x]);
		}
		if (op == '?') {
			int q;
			cin >> q;
			ll ans = SegQuery(1, 1, n, 1, q) - q - (BITQuery(MAXB) - BITQuery(q));
			cout << ans << '\n';
		}
	}
	return 0;
}

L

Solved: 00:11 (BPM136)
温暖的签到

#include <bits/stdc++.h>

using namespace std;

using ll = long long;

int const N = 100005;

vector<int> v[N];

int main() {
	int n, m;
	cin >> n >> m;
	static int a[N], b[N];
	for (int i = 1; i <= n; ++i) 
		cin >> a[i];
	for (int i = 1; i <= n; ++i)
		cin >> b[i];

	for (int i = 1; i <= n; ++i) 
		v[a[i]].push_back(b[i]);
	for (int i = 1; i <= m; ++i)
		sort(v[i].begin(), v[i].end(), greater<int>());
	auto tot = vector<int>();
	int nee = 0;
	for (int i = 1; i <= m; ++i) {
		if (v[i].size() > 1u) 
			for (int j = 1; j < v[i].size(); ++j)
				tot.push_back(v[i][j]);
		if (v[i].size() == 0u)
			++nee;
	}
	sort(tot.begin(), tot.end());
	ll ans = 0;
	for (int i = 0; i < nee; ++i)
		ans += tot[i];
	cout << ans << '\n';
	return 0;
}
close

M

Upsolved by BPM136
比赛的时候构造是有锅的
我们可以先强联通分量缩点再拓扑排序
每一层一共有3行
长度为边数*2
对于每个强联通分量的点都放在同一层的第3行
前两行如果一个强联通分量到另一个强联通分量有边
那就把对应序号的位置造一堵墙围住
也就是
12345
.#.#.#.#.#.#
.#.#.#.#.#.#
如果围住,那就是
12345
.###.#.###.#
.#.#.#.#.#.#

#include <bits/stdc++.h>

using namespace std;

int const N = 20;
int const M = 200;

struct edge {
	int y, next;
}e1[M], e2[M];
int last1[N], last2[N];
int ne1 = 0, ne2 = 0;
bool vis1[N], vis2[N];

void addch(int x, int y) {
	e1[++ne1].y = y;
	e1[ne1].next = last1[x];
	last1[x] = ne1;

	e2[++ne2].y = x;
	e2[ne2].next = last2[y];
	last2[y] = ne2;
}

int st[N];
int belong[N];
int num;
int setNum[N];
int cnt1, cnt2;
int n;
int a[N][N];

void dfs1(int x) {
	vis1[x] = 1;
	for (int i = last1[x]; i != 0; i = e1[i].next) 
		if (vis1[e1[i].y] == 0) 
			dfs1(e1[i].y);
	st[cnt1++] = x;
}

void dfs2(int x) {
	vis2[x] = 1;
	++num;
	belong[x] = cnt2;
	for (int i = last2[x]; i != 0; i = e2[i].next) 
		if (vis2[e2[i].y] == 0)
			dfs2(e2[i].y);
}

void Kosaraju() {
	for (int i = 1; i <= n; ++i) 
		for (int j = 1; j <= n; ++j) 
			if (a[i][j]) 
				addch(i, j);
	memset(vis1, 0, sizeof(vis1));
	memset(vis2, 0, sizeof(vis2));
	cnt1 = cnt2 = 0;
	for (int i = 1; i <= n; ++i) 
		if (vis1[i] == 0)
			dfs1(i);
	for (int i = cnt1 - 1; i >= 0; --i) 
		if (vis2[st[i]] == 0) {
			num = 0;
			++cnt2;
			dfs2(st[i]);
			setNum[cnt2] = num;
		}
}



int ma[N][N];

vector<int> TopoSort() {
	queue<int> Q;
	static int du[N];
	memset(du, 0, sizeof(du));
	for (int i = 1; i <= cnt2; ++i) 
		for (int j = 1; j <= cnt2; ++j) 
			if (ma[i][j])
				++du[j];
	for (int i = 1; i <= cnt2; ++i) 
		if (du[i] == 0) 
			Q.push(i);
	auto ret = vector<int>();
	while (Q.empty() == 0) {
		int now = Q.front();
		Q.pop();
		ret.push_back(now);
		for (int i = 1; i <= cnt2; ++i) 
			if (ma[now][i] && du[i]) {
				--du[i];
				if (du[i] == 0) 
					Q.push(i);
			}
	}
	return ret;
}

int f[N * N][4][N * 2];

void Output(vector<int> &ver) {
	int len_x = n * n * 2;
	int len_y = 3;
	int len_z = 2 * cnt2;
	cout << len_x << ' ' << len_y << ' ' << len_z << '\n';
	for (int i = 1; i <= cnt2; ++i) 
		for (int j = 1; j <= len_x; ++j) 
			for (int k = 1; k <= len_y; ++k)
				f[j][k][i * 2 - 1] = -1;

	for (int i = 1; i <= cnt2; ++i) {
		int fl = cnt2 - i + 1;
		fl = fl * 2;
		int tmpn = 0;
		for (int j = 1; j <= n; ++j) 
			if (belong[j] == ver[i - 1]) 
				f[++tmpn][3][fl] = j;

		for (int j = 1; j <= cnt2 * cnt2; ++j)
			f[j * 2][1][fl] = f[j * 2][2][fl] = -1;
	}
	
	for (int i = 1; i <= cnt2; ++i)
		for (int j = 1; j <= cnt2; ++j) 
			if (ma[ver[i - 1]][ver[j - 1]]) {
				int fl_i = cnt2 - i + 1;
				int fl_j = cnt2 - j + 1;
				fl_i = fl_i * 2;
				fl_j = fl_j * 2;
				--fl_i;
				++fl_j;
				for (int k = fl_j; k <= fl_i; ++k) {
					f[((i - 1) * cnt2 + j) * 2 - 1][1][k] = 0;
					f[((i - 1) * cnt2 + j) * 2 - 1][2][k] = -1;
				}
			}
	for (int o = len_z; o >= 1; --o) {
		for (int j = 1; j <= len_y; ++j) {
			for (int i = 1; i <= len_x; ++i) {
				if (f[i][j][o] == 0)
					cout << '.';
				else if (f[i][j][o] == -1)
					cout << '#';
				else
					cout << f[i][j][o];
			}
			cout << '\n';
		}
		cout << '\n';
	}
}

int main() {
	ios::sync_with_stdio(0);
	cin >> n;
	for (int i = 1; i <= n; ++i) 
		for (int j = 1; j <= n; ++j)
			cin >> a[i][j];

	Kosaraju();
	memset(ma, 0, sizeof(ma));
	for (int i = 1; i <= n; ++i) 
		for (int j = 1; j <= n; ++j) 
			if (a[i][j]) 
				ma[belong[i]][belong[j]] = 1;
	for (int i = 1; i <= cnt2; ++i)
		ma[i][i] = 0;
	auto ver = TopoSort();
	Output(ver);
	return 0;
}
close
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值