考虑到乘出来的东西实际上不多。。。直接map记下。
然后比如说x位的计数,就把ceil(x/2)和trunc(x/2)的情况乘起来。
然后就是一个ai,j=tab[i]*tab[j],求这个数表前k大的问题。
这个可以排序,然后单调队列,把状态慢慢往后推就行了。(注意到ai,j都不用取模才可以这么做,否则。。。我也不知道怎么做)
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<map> #include<queue> #include<cmath> #define maxn 1000050 #define mod 1000000007 using namespace std; long long n,k,bit[20],ret=0,a[maxn],tot=0; long long ans=0; map <long long,long long> tab[7],mp; map <pair<long long,long long>,long long> vis; map <long long,long long>::iterator it1,it2; struct status { long long p1,p2; long long val; status (long long p1,long long p2,long long val):p1(p1),p2(p2),val(val) {} status () {} friend bool operator < (const status &x,const status &y) { return x.val<y.val; } }; priority_queue <status> q; bool cmp(long long x,long long y) {return x>y;} void pre_dfs(long long now,long long ret) { if (now-1) tab[now-1][ret]++; if (now==7) return; for (long long i=1;i<=9;i++) pre_dfs(now+1,ret*i); } void get_bit(long long x) { ret=0; while (x) {bit[++ret]=x%10;x/=10;} } void update(long long ret,long long x) { if (!x) {mp[ret]++;return;} if (!(x-1)) {for (long long i=1;i<=9;i++) mp[ret*i]++;return;} long long l=ceil((double)x/2),r=trunc((double)x/2); for (it1=tab[l].begin();it1!=tab[l].end();it1++) for (it2=tab[r].begin();it2!=tab[r].end();it2++) mp[ret*(it1->first)*(it2->first)]+=it1->second*it2->second; } void digit_dp() { for (long long i=1;i<=ret-1;i++) update(1,i); long long rets=1; for (long long i=ret;i>=1;i--) { for (long long j=1;j<bit[i];j++) update(rets*j,i-1); rets*=bit[i]; } mp[rets]++; } int main() { scanf("%lld%lld",&n,&k); pre_dfs(1,1); get_bit(n); digit_dp(); for (it1=mp.begin();it1!=mp.end();it1++) { if (!it1->first) continue; a[++tot]=it1->second; } sort(a+1,a+tot+1,cmp); q.push(status(1,1,(long long)a[1]*a[1])); long long tr=0; for (long long i=1;i<=k;i++) { tr++; status now=q.top();q.pop(); if (vis[make_pair(now.p1,now.p2)]) {i--;continue;} ans=(ans+now.val%mod)%mod;vis[make_pair(now.p1,now.p2)]=1; q.push(status(now.p1,now.p2+1,(long long)a[now.p1]*a[now.p2+1])); q.push(status(now.p1+1,now.p2,(long long)a[now.p1+1]*a[now.p2])); } printf("%lld\n",ans%mod); return 0; }