BZOJ 3131 淘金

考虑到乘出来的东西实际上不多。。。直接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
",ans%mod);
    return 0;
}
原文地址:https://www.cnblogs.com/ziliuziliu/p/6285570.html