您的位置:首页 > 其它

bzoj 3131: [Sdoi2013]淘金

2016-03-22 23:20 405 查看
#include<cstdio>
#include<iostream>
#include<queue>
#include<algorithm>
#define ll long long
#define M 40009
#define MO 1000000007
using namespace std;
int a[15],tot,K,anss;
ll ans[10*M],n,f[15][M][2],size[M],m;
struct data
{
int x,y;
ll z;
data(int a1,int a2)
{
x=a1;
y=a2;
z=size[x]*size[y];
}
bool operator <(data a1)const
{
return z<a1.z;
}
};
void dfs(int wei,ll a1,int now)
{
if(a1>m)
return;
if(wei==tot)
{
ans[++ans[0]]=a1;
return;
}
for(int i=now;i<10;i++)
dfs(wei+1,a1*i,i);
return;
}
bool cmp(ll a1,ll a2)
{
return a1>a2;
}
int main()
{
scanf("%lld%d",&n,&K);
m=n;
for(;n;n/=10)
a[++tot]=n%10;
dfs(0,1,1);
sort(ans+1,ans+ans[0]+1);
ans[0]=unique(ans+1,ans+ans[0]+1)-ans-1;
f[0][1][0]=1;
for(int i=0;i<tot;i++)
{
for(int j=1;j<=ans[0];j++)
for(int k=0;k<2;k++)
if(f[i][j][k])
for(int l=1;l<10;l++)
{
ll a1=ans[j]*l;
if(a1>ans[ans[0]])
continue;
a1=lower_bound(ans+1,ans+ans[0]+1,a1)-ans;
f[i+1][a1][(k+l)>a[i+1]]+=f[i][j][k];
}
}
for(int i=1;i<ans[0];i++)
for(int j=1;j<tot;j++)
size[i]+=f[j][i][0]+f[j][i][1];
for(int i=1;i<=ans[0];i++)
size[i]+=f[tot][i][0];
sort(size+1,size+ans[0]+1,cmp);
priority_queue<data> p;
p.push(data(1,1));
for(;!p.empty();)
{
K--;
data q=p.top();
p.pop();
anss=(anss+q.z)%MO;
if(!K)
break;
if(q.x!=q.y)
{
anss=(anss+q.z)%MO;
K--;
if(!K)
break;
p.push(data(q.x+1,q.y));
}
if(q.x==1)
p.push(data(q.x,q.y+1));
}
printf("%d",anss);
return 0;
}


DP求出转移到x坐标的数目。各位数乘积的实际数目少。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: