AtCoder Regular Contest 129 C Multiple of 7

洛谷传送门

AtCoder 传送门

首先 \(\text{7777...777}\)\(x\)\(7\))对能被 \(7\) 整除子串数量的贡献是 \(\frac{x(x+1)}{2}\)

\(n\) 分解成若干 \(x_i\) 使得 \(\sum\limits_{i=1}^m \frac{x_i(x_i+1)}{2} = n\),表示每段 \(x_i\)\(7\)。怎么把它们组合在一起呢?

一个 naive 的想法是 \(\text{77...77a77...77a}\),其中 \(a\) 为指定的数。发现怎么指定,中间都会串出一段 \(7\) 的倍数。

既然不能指定,那么就随机好了!随机得出每段 \(7\) 之间间隔的数,直到合法就输出,可过。

code
// Problem: C - Multiple of 7
// Contest: AtCoder - AtCoder Regular Contest 129
// URL: https://atcoder.jp/contests/arc129/tasks/arc129_c
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mems(a, x) memset((a), (x), sizeof(a))

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ldb;
typedef pair<ll, ll> pii;

const int maxn = 1000100;

int n, m;
char s[maxn];

void solve() {
	scanf("%d", &n);
	int t = n;
	vector<int> vc;
	while (n) {
		int l = 1, r = 1e4, pos = -1;
		while (l <= r) {
			int mid = (l + r) >> 1;
			if (mid * (mid + 1) / 2 <= n) {
				pos = mid;
				l = mid + 1;
			} else {
				r = mid - 1;
			}
		}
		vc.pb(pos);
		n -= pos * (pos + 1) / 2;
	}
	mt19937 rnd(time(NULL));
	while (1) {
		m = 0;
		for (int x : vc) {
			for (int _ = 0; _ < x; ++_) {
				s[++m] = '7';
			}
			s[++m] = '1' + rnd() % 9;
		}
		int cnt = 0;
		for (int i = 1; i <= m; ++i) {
			int x = 0;
			for (int j = i; j <= m; ++j) {
				x = (x * 10 + s[j] - '0') % 7;
				cnt += (!x);
			}
		}
		if (cnt == t) {
			break;
		}
	}
	printf("%s\n", s + 1);
}

int main() {
	int T = 1;
	// scanf("%d", &T);
	while (T--) {
		solve();
	}
	return 0;
}

posted @ 2023-05-12 22:25  zltzlt  阅读(31)  评论(0)    收藏  举报