原題連接
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; }