9
10
2015
3

NOIP2012提高组

D1T1 vigenere密码

  维吉尼亚方表是个好东西,多表替代相比神奇的单表替代的凯撒密码什么的是差距大了去了。随机性分析也是无效的。手工的话只有猜密钥位数攻击了。然并卵。

  模拟大法好啊,觉得自己还是写的比较漂亮的。

#include <cstdio>
#include <cstring>
int n, m;
char key[101], arr[1001];

inline int solve(int a, int b) {
	return (a + (26 - b)) % 26;
}

int main() {
	scanf("%s", key); m = strlen(key);
	scanf("%s", arr); n = strlen(arr);
	for (int i = 0; i < n; i++) {
		int t;
		if ('a' <= key[i % m] && key[i % m] <= 'z') t = key[i % m] - 'a';
			else t = key[i % m] - 'A';
		if ('a' <= arr[i] && arr[i] <= 'z')
			printf("%c", (char) ('a' + solve(arr[i] - 'a', t)));
		else
			printf("%c", (char) ('A' + solve(arr[i] - 'A', t)));
	}
	printf("\n");
	return 0;
}

D2T2 国王游戏

  贪心+高精度。正确性证明我拉一段。

假设相邻的两个人左右手分别是(a, b), (A, B)。设a * b <= A * B,i之前所有人的左手乘积为S。
则,ans1 = max{S / b, S * a / B}
若交换
则,ans2 = max{S / B, S * A / b}
因为,a * b <= A * B
所以,S * a / B <= S * A / b
又因为,S / B <= S * a / B
所以,ans2 = S * A / b
ans1 = max{S / B[i], S * a / B}
所以,ans1 <= ans2
证毕

  自己写的高精度乘单精度一开始返回大数的位数判错了,后来改对了。

#include <algorithm>
#include <cstring>
using std :: sort;
struct Sec {
	int a, b;
} sec[1001], king;
struct bignum {
	int l, a[5000];
	
	bignum () {
		l = 1; memset(a, 0, sizeof(a));
	}
	
	bignum (int n) {
		l = 0; memset(a, 0, sizeof(a));
		while (n) {
			a[++l] = n % 10; n /= 10;
		}
	}
};
int n;

bool cmp(Sec x, Sec y) {
	if (x.a * x.b < y.a * y.b) return true;
		else return false;
}

bignum operator + (bignum A, bignum B) {
	bignum ret;
	ret.l = A.l > B.l ? A.l : B.l;
	for (int i = 1; i <= ret.l; i++) {
		ret.a[i] += A.a[i] + B.a[i];
		if (ret.a[i] > 9)
			ret.a[i + 1]++, ret.a[i] -= 10;
	}
	if (ret.a[ret.l + 1]) ret.l++;
	return ret;
}

bignum operator / (bignum A, int B) {
	bignum ret;
	int cnt = 0;
	for (int i = A.l; i >= 1; i--) {
		cnt += A.a[i];
		if (cnt >= B) {
			ret.a[i] = cnt / B;
			cnt %= B;
		}
		cnt *= 10;
	}
	ret.l = A.l;
	while (ret.a[ret.l] == 0 && ret.l > 1) ret.l--;
	return ret;
}

bignum operator * (bignum A, int B) {
	bignum ret; ret.l = A.l;
	for (int i = 1; i <= A.l; i++) {
		ret.a[i] += A.a[i] * B;
		int k = i;
		while (ret.a[k] > 9) {
			ret.a[k + 1] += ret.a[k] / 10; ret.a[k++] %= 10;
		}
		if (k > ret.l) ret.l = k;
	}
	return ret;
}

bool operator > (bignum A, bignum B) {
	if (A.l != B.l) return A.l > B.l;
	for (int i = A.l; i >= 1; i--) {
		if (A.a[i] > B.a[i]) return 1;
		if (A.a[i] < B.a[i]) return 0;
	}
	return 0;
}

void print(bignum A) {
	for (int i = A.l; i >= 1; i--) printf("%d", A.a[i]);
	printf("\n");
}

int main() {
	scanf("%d", &n);
	scanf("%d%d", &king.a, &king.b);
	for (int i = 1; i <= n; i++)
		scanf("%d%d", &sec[i].a, &sec[i].b);
	sort(sec + 1, sec + n + 1, cmp);
	bignum tmp = king.a, ans = 0;
	for (int i = 1; i <= n; i++) {
		bignum k = tmp / sec[i].b;
		if (k > ans) ans = k;
		tmp = tmp * sec[i].a;
	}
	print(ans);
	return 0;
}
Category: 未分类 | Tags: NOIP 提高组 2012

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com