原题连接
ios
首先能够考虑最简单的一种构造方式,开头为133,后面接n个7,这样必定是正确的,可是长度会超过限定
spa
咱们注意到上面那种方法,每增长一个7,1337子序列数量会增长1,增长速度比较慢,因此咱们寻找一种新的“逼近n”的增加方法——也就是每增长一个7,1337的数量增长量为一个变量
code
由于7前面是3,咱们考虑增长3的数量以后,再逐个增长7的数量
get
咱们发现,若是在增长的一个7前方有m个3,则1337子序列增长量为string
这里其实也就正好达到了咱们以前提到的目的,让每次增长量为变量,咱们能够假设一开始1后面有无数的3,而后咱们从这些3中间插入7,每次插入的贡献值显然就是由上面的式子来算出。咱们设为 \(f(m)\)
it
那么如何使得咱们插入的k个7的贡献值的和为n?,也就是io
(a_i为每次加入7时前方的3个数)
class
咱们能够对n 不断减去小于等于它的最大f(m)(若是为了容易思考,可使用二分逼近),同时记录这个m,直到n等于0。这样,咱们也就获得了上面的a_i
stream
以后将a_i从小到大排列,不断输出补充3达到对应的a_i数量,而后结尾加上7,将全部a_i操做完以后,答案也就构造完毕了。
变量
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; long long n; int t; long long aa[100005], co = 0; long long search(long long x) { long long l = 2, r = x * 2; while (l + 5 <= r) { long long mid = (l + r) >> 1; if ((mid - 1) * mid / 2 <= x) { l = mid; } else { r = mid - 1; } } while ((l - 1) * l / 2 <= x) { ++l; } return l - 1; } int main() { scanf("%d", &t); while (t--) { co = 0; scanf("%lld", &n); printf("1"); while (n) { long long x = search(n); aa[++co] = x; n -= x * (x - 1) / 2; } int ll = 0; for (int i = co; i >= 1; --i) { while (ll < aa[i]) { printf("3"); ++ll; } printf("7"); } printf("\n"); } return 0; }