# Solution

$(i, j)$可以转移到$(i + 1, j)$$(i, j + 1)$，但是这样直接转移会有一个小问题，$(i - 1, j)$$(i, j - 1)$都能转移到$(i, j)$，所以再记录一下上一次是不是将$j$加一，如果上次将$j$加一，那么这次不能再将$i$加一。

# Code

/*
_______                       ________                        _______
/ _____ \                     / ______ \                      / _____ \
/ /     \_\  _     __     _   / /      \ \   _     __     _   / /     \_\
| |          | |   |  |   | | | |        | | | |   |  |   | | | |
| |          | |   |  |   | | | |     __ | | | |   |  |   | | | |
| |       __ \  \  |  |  /  / | |     \ \| | \  \  |  |  /  / | |       __
\ \_____/ /  \  \/ /\ \/  /   \ \_____\  /   \  \/ /\ \/  /   \ \_____/ /
\_______/    \___/  \___/     \______/\__\   \___/  \___/     \_______/
*/
#include <iostream>
#include <queue>
#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;

#define ll long long
#define RE register

const int HashMOD = 100077;
const int MOD = 1e9 + 7;

int k, head[HashMOD + 5], num, fa[20], shu[20], len, tot[10005], ans;

ll dp[14][10005][2];

ll n;

struct Node {
int next;
ll to;
} edge[HashMOD + 5];

struct HeapNode {
int pos1, pos2;
ll qz;
bool flag;
bool operator < (const HeapNode &rhs) const {
return qz < rhs.qz;
}
};

int pos = x % HashMOD;
for (RE int i = head[pos]; i; i = edge[i].next) {
ll v = edge[i].to;
if (v == x) return;
}
return;
}

inline int Find(ll x) {
int pos = x % HashMOD;
for (RE int i = head[pos]; i; i = edge[i].next) {
ll v = edge[i].to;
if (v == x) return i;
}
return 0;
}

inline ll Ksm(ll a, int b) {
ll tmp = 1;
while (b) {
if (b & 1) tmp = tmp * a;
a = a * a;
b >>= 1;
}
return tmp;
}

void Work() {
ll tmp = 1;
for (RE ll i = 1; i <= 9; i++)
tmp *= Ksm(i, fa[i]);
return;
}

void Dfs(int x, int sum) {
if (x == 10 || sum == 12) {
Work();
return;
}
for (RE int i = 0; i <= 12 - sum; i++)
fa[x] = i, Dfs(x + 1, sum + i);
return;
}

void Solve(ll n) {
ll tmp = n;
while (n) {
shu[++len] = n % 10;
n /= 10;
}
for (RE int i = 1; i <= shu[len]; i++) dp[len][Find(i)][i == shu[len]] = 1;
for (RE int i = len - 1; i >= 1; i--) {
for (RE int now = 1; now <= 9; now++)
dp[i][Find(now)][0]++;
for (RE int lst = 1; lst <= num; lst++)
for (RE int p = 0; p <= 1; p++)
if (dp[i + 1][lst][p]) {
for (RE int now = 1; now <= (p ? shu[i] : 9); now++) {
ll ne = edge[lst].to * now;
dp[i][Find(ne)][p && (now == shu[i])] += dp[i + 1][lst][p];
}
}
}
for (RE int i = 1; i <= num; i++)
if (edge[i].to <= tmp)
tot[i] += dp[1][i][0] + dp[1][i][1];
return;
}

bool Cmp(int a, int b) {
return a > b;
}

void Qm(int &x) {
x -= MOD;
x += x >> 31 & MOD;
return;
}

void Calc(int k) {
sort(tot + 1, tot + num + 1, Cmp);
priority_queue<HeapNode> q;
q.push((HeapNode){1, 1, 1LL * tot[1] * tot[1] % MOD, false});
while (!q.empty() && k) {
HeapNode tmp = q.top(); q.pop();
int pos1 = tmp.pos1, pos2 = tmp.pos2;
if (!tmp.qz) break;
k--;
Qm(ans += tmp.qz % MOD);
if (pos1 <= num && tmp.flag == false) q.push((HeapNode){pos1 + 1, pos2, 1LL * tot[pos1 + 1] * tot[pos2], false});
if (pos2 <= num) q.push((HeapNode){pos1, pos2 + 1, 1LL * tot[pos1] * tot[pos2 + 1], true});
}
return;
}

int main() {
Dfs(1, 0);
scanf("%lld%d", &n, &k);
Solve(n);
Calc(k);
printf("%d", ans);
return 0;
}

posted @ 2020-11-17 17:47  Tian-Xing  阅读(58)  评论(0编辑  收藏  举报