CodeForces 478E Wavy numbers

本文介绍了一种求解特定条件下波浪数的算法。通过分治策略与优化的哈希表实现,针对输入的n和k,找到满足条件的第k小的波浪数。代码实现中使用了高效的离散化哈希方法来提高运行效率。

题意:

如果一个数它的每一位(除了最高最低位)都大于或小于它两边的数字  则这个数字叫波浪数  输入n和k (10^14)  求%n==0的第k小的波浪数  如果没有或者大于10^14就输出-1

思路:

这也算是一种分治的搜索策略吧  meet-in-mid

由于数字最多14位  因此可以暴力高7位和低7位(均为80+w种)  然后枚举高位和低位去拼

这题对于代码书写要求较高!!  我的方法如下:

暴力高7位

暴力低7为  放进vector  同时记录对于一个number  它的首位  和  首位与第二位大小情况(为了拼接)  同时做一个hash  记录cnt[i][j][k]  其中i为number首位  j为0或1表示首位与第二位大小情况  k为number%n的余数的hash值(为了方便查找)cnt记录ijk情况的number个数

然后开始寻找答案

枚举高7位的number  表示只有不用拼接的情况

判断n是否大于等于10^7  如果是  那么只要i=n开始不断的+n就可以找数字了

如果不是  枚举高7位  再枚举低7位的首位  利用刚才记录的cnt不断的使k减小  直到确定了高7位后  暴力低7位拼答案

注意:hash不能用map  会TLE  在叉姐的提醒下我改成了离散再hash(因为种类不多!!)  现在是CF上跑的最快的代码哈哈哈哈哈哈哈~~~

代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<cstdlib>
#include<ctime>
#include<cmath>
using namespace std;
typedef long long LL;
#define N 850000
#define M 10000000

LL n, k;
int tothigh;
int anshigh[N];
vector<int> anslow[10][2];
int id, to[M], cnt[10][2][N];
int dig[10];

void get_high(int bit) {
	int num = 0, i = bit;
	while (i) {
		num = num * 10 + dig[i];
		i--;
	}
	anshigh[tothigh++] = num;
}

void find_high(int bit) {
	for (int i = 0; i <= 9; i++) {
		if (i != dig[bit - 1]) {
			if (bit <= 2
					|| (bit > 2
							&& ((i > dig[bit - 1] && dig[bit - 2] > dig[bit - 1])
									|| (i < dig[bit - 1]
											&& dig[bit - 2] < dig[bit - 1])))) {
				dig[bit] = i;
				if (i)
					get_high(bit);
				if (bit < 7)
					find_high(bit + 1);
			}
		}
	}
}

void get_low() {
	int num = 0, i = 7;
	while (i) {
		num = num * 10 + dig[i];
		i--;
	}
	if (dig[7] < dig[6]) {
		anslow[dig[7]][0].push_back(num);
		if (!to[num % n])
			to[num % n] = ++id;
		cnt[dig[7]][0][to[num % n]]++;
	} else {
		anslow[dig[7]][1].push_back(num);
		if (!to[num % n])
			to[num % n] = ++id;
		cnt[dig[7]][1][to[num % n]]++;
	}
}

void find_low(int bit) {
	for (int i = 0; i <= 9; i++) {
		if (i != dig[bit - 1]) {
			if (bit <= 2
					|| (bit > 2
							&& ((i > dig[bit - 1] && dig[bit - 2] > dig[bit - 1])
									|| (i < dig[bit - 1]
											&& dig[bit - 2] < dig[bit - 1])))) {
				dig[bit] = i;
				if (bit == 7)
					get_low();
				else
					find_low(bit + 1);
			}
		}
	}
}

bool check(LL x) {
	int a = x % 10;
	x /= 10;
	int b = x % 10;
	x /= 10;
	while (x) {
		int c = x % 10;
		x /= 10;
		if ((b > a && b > c) || (b < a && b < c))
			;
		else
			return false;
		a = b;
		b = c;
	}
	return true;
}

int main() {
	scanf("%lld%lld", &n, &k);
	dig[0] = -1;
	find_high(1);
	find_low(1);
	sort(anshigh, anshigh + tothigh);
	for (int i = 0; i < tothigh; i++) {
		if (anshigh[i] % n == 0) {
			k--;
			if (!k) {
				printf("%d\n", anshigh[i]);
				return 0;
			}
		}
	}
	if (n >= M) {
		for (LL i = n; i <= 100000000000000LL; i += n) {
			if (check(i)) {
				k--;
				if (!k) {
					printf("%lld\n", i);
					return 0;
				}
			}
		}
	} else
		for (int i = 0; i < tothigh; i++) {
			int r = to[(n - (LL) anshigh[i] * M % n) % n];
			if (!r)
				continue;
			if (anshigh[i] < 10) {
				for (int j = 0; j <= 9; j++) {
					if (j == anshigh[i])
						continue;
					if (j > anshigh[i]) {
						if (cnt[j][1][r]) {
							if (k > cnt[j][1][r])
								k -= cnt[j][1][r];
							else {
								sort(anslow[j][1].begin(), anslow[j][1].end());
								for (int it = 0; it < anslow[j][1].size();
										it++) {
									if (to[anslow[j][1][it] % n] == r) {
										k--;
										if (!k) {
											printf("%d%07d\n", anshigh[i],
													anslow[j][1][it]);
											return 0;
										}
									}
								}
							}
						}
					} else {
						if (cnt[j][0][r]) {
							if (k > cnt[j][0][r])
								k -= cnt[j][0][r];
							else {
								sort(anslow[j][0].begin(), anslow[j][0].end());
								for (int it = 0; it < anslow[j][0].size();
										it++) {
									if (to[anslow[j][0][it] % n] == r) {
										k--;
										if (!k) {
											printf("%d%07d\n", anshigh[i],
													anslow[j][0][it]);
											return 0;
										}
									}
								}
							}
						}
					}
				}
			} else {
				if (anshigh[i] % 10 > anshigh[i] / 10 % 10) {
					for (int j = 0; j < anshigh[i] % 10; j++) {
						if (cnt[j][0][r]) {
							if (k > cnt[j][0][r])
								k -= cnt[j][0][r];
							else {
								sort(anslow[j][0].begin(), anslow[j][0].end());
								for (int it = 0; it < anslow[j][0].size();
										it++) {
									if (to[anslow[j][0][it] % n] == r) {
										k--;
										if (!k) {
											printf("%d%07d\n", anshigh[i],
													anslow[j][0][it]);
											return 0;
										}
									}
								}
							}
						}
					}
				} else {
					for (int j = anshigh[i] % 10 + 1; j <= 9; j++) {
						if (cnt[j][1][r]) {
							if (k > cnt[j][1][r])
								k -= cnt[j][1][r];
							else {
								sort(anslow[j][1].begin(), anslow[j][1].end());
								for (int it = 0; it < anslow[j][1].size();
										it++) {
									if (to[anslow[j][1][it] % n] == r) {
										k--;
										if (!k) {
											printf("%d%07d\n", anshigh[i],
													anslow[j][1][it]);
											return 0;
										}
									}
								}
							}
						}
					}
				}
			}
		}
	printf("-1\n");
	return 0;
}


### Codeforces 887E Problem Solution and Discussion The problem **887E - The Great Game** on Codeforces involves a strategic game between two players who take turns to perform operations under specific rules. To tackle this challenge effectively, understanding both dynamic programming (DP) techniques and bitwise manipulation is crucial. #### Dynamic Programming Approach One effective method to approach this problem utilizes DP with memoization. By defining `dp[i][j]` as the optimal result when starting from state `(i,j)` where `i` represents current position and `j` indicates some status flag related to previous moves: ```cpp #include <bits/stdc++.h> using namespace std; const int MAXN = ...; // Define based on constraints int dp[MAXN][2]; // Function to calculate minimum steps using top-down DP int minSteps(int pos, bool prevMoveType) { if (pos >= N) return 0; if (dp[pos][prevMoveType] != -1) return dp[pos][prevMoveType]; int res = INT_MAX; // Try all possible next positions and update 'res' for (...) { /* Logic here */ } dp[pos][prevMoveType] = res; return res; } ``` This code snippet outlines how one might structure a solution involving recursive calls combined with caching results through an array named `dp`. #### Bitwise Operations Insight Another critical aspect lies within efficiently handling large integers via bitwise operators instead of arithmetic ones whenever applicable. This optimization can significantly reduce computation time especially given tight limits often found in competitive coding challenges like those hosted by platforms such as Codeforces[^1]. For detailed discussions about similar problems or more insights into solving strategies specifically tailored towards contest preparation, visiting forums dedicated to algorithmic contests would be beneficial. Websites associated directly with Codeforces offer rich resources including editorials written after each round which provide comprehensive explanations alongside alternative approaches taken by successful contestants during live events. --related questions-- 1. What are common pitfalls encountered while implementing dynamic programming solutions? 2. How does bit manipulation improve performance in algorithms dealing with integer values? 3. Can you recommend any online communities focused on discussing competitive programming tactics? 4. Are there particular patterns that frequently appear across different levels of difficulty within Codeforces contests?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值