SRM 620

easy: 

两个数要向上还原一步的话,肯定是大减小。然后两组数谁比较大,谁就向上还原一步。


medium: 

我们试想最后一次排序是什么样,就是和最终序列大小关系必须满足,但是有些相等的我们并不能保证可以排成最后的样子。

那么倒数第二次排序呢?即最后一次排序的那些可以保证关系我们可以不用管,其他的关系必须满足。。。

这样我们就能一直划分成一段一段。。。最后每个数单独一段就是possible

因为我们不知道几次可以完成,我们迭代超过m次,再接着迭代肯定是无用的。

(讲不太清楚,我把代码贴上来,flag[i]表示i与i+1有没有被隔开

代码:

#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstring>

using namespace std;

class CandidatesSelection {
public:
	string possible(vector<string> , vector<int> );
};

bool flag[55];
string CandidatesSelection::possible(vector<string> score, vector<int> result) {
	int i, j, k, n, m;
	n = score.size();
	m = score[0].size();
	memset(flag, 0, sizeof(flag));
	for (j = 0; j < m + 2; ++j) {
		for (k = 0; k < m; ++k) {
			bool f = true;
			for (i = 0; i < n - 1; ++i) {
				if (flag[i])
					continue;
				if (score[result[i]][k] > score[result[i + 1]][k]) {
					f = false;
					break;
				}
			}
			if (f == false)
				continue;
			for (i = 0; i < n - 1; ++i) {
				if (flag[i])
					continue;
				if (score[result[i]][k] < score[result[i + 1]][k]) {
					flag[i] = true;
				}
			}
		}
	}
	bool f = true;
	for (i = 0; i < n - 1; ++i) {
		if (flag[i])
			continue;
		if (result[i] < result[i + 1]) {
			flag[i] = true;
		}
		if (flag[i] == false)
			f = false;
	}
	if (f)
		return "Possible";
	else
		return "Impossible";
}


hard:

看到counting,我刚开始以为是dp。。。其实是个高斯消元。。。

首先对于每个素数,如果一个数它包含这个素数奇数次,那么这种数必须出现偶数次

这样可以对于每个素数列一个方程

然后对于每一行每一列,再列一个方程

然后解出这个方程的自由元个数,2^自由元个数 就是答案。

代码:

#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstring>

using namespace std;

class PerfectSquare {
public:
	int ways(vector<int> );
};
const int maxn = 10005;
int a[maxn][450], y[maxn];

int Gauss(int x[maxn], int n, int m) {
	int i, j, k;
	int now;
	now = 0;
	for (i = 0; i < n; ++i) {
		for (j = now; j < m; ++j) {
			if (a[j][i] == 1) {
				if (j == now)
					break;
				for (k = 0; k <= n; ++k)
					a[now][k] ^= a[j][k];
				break;
			}
		}
		if (j == m)
			continue;
		for (j = now + 1; j < m; ++j) {
			if (a[j][i] == 0)
				continue;
			for (k = 0; k <= n; ++k)
				a[j][k] ^= a[now][k];
		}
		now++;
	}
	for (j = now; j < m; ++j)
		if (a[j][n] == 1)
			return -1;
	return n - now;
}

map<int, int> m;
int ed;
vector<int> v[100000];
int PerfectSquare::ways(vector<int> x) {
	int n, i, j, k, p;
	n = x.size();
	m.clear();
	ed = 1;
	for (i = 0; i < n; ++i) {
		int j = x[i];
		for (k = 2; k * k <= j; ++k) {
			if (j % k == 0) {
				int cnt = 0;
				while (j % k == 0) {
					cnt++;
					j /= k;
				}
				if (cnt % 2) {
					p = m[k];
					if (p == 0) {
						p = ed;
						m[k] = ed++;
						v[p].clear();
					}
					v[p].push_back(i);
				}
			}
		}
		if (j != 1) {
			p = m[j];
			if (p == 0) {
				p = ed;
				m[j] = ed++;
				v[p].clear();
			}
			v[p].push_back(i);
		}
	}
	memset(a, 0, sizeof(a));
	for (j = 1; j < ed; ++j) {
		for (k = 0; k < v[j].size(); ++k) {
			a[j - 1][v[j][k]] = 1;
		}
		a[j - 1][n] = 0;
	}
	int nn = sqrt((double) n);
	for (i = 0; i < nn; ++i) {
		for (j = 0; j < nn; ++j) {
			a[ed - 1][i * nn + j] = 1;
		}
		a[ed - 1][n] = 1;
		ed++;
	}
	for (j = 0; j < nn; ++j) {
		for (i = 0; i < nn; ++i) {
			a[ed - 1][i * nn + j] = 1;
		}
		a[ed - 1][n] = 1;
		ed++;
	}
	int ans = Gauss(y, n, ed - 1);
	if (ans < 0)
		return 0;
	int pmod = 1000000007;
	int aans = 1;
	for (i = 0; i < ans; ++i)
		aans = aans * 2 % pmod;
	return aans;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值