bzoj3131 [Sdoi2013]淘金

Posted Forever_goodboy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj3131 [Sdoi2013]淘金相关的知识,希望对你有一定的参考价值。

 [Sdoi2013]淘金

Time Limit: 30 Sec  Memory Limit: 256 MB

Description

小Z在玩一个叫做《淘金者》的游戏。游戏的世界是一个二维坐标。X轴、Y轴坐标范围均为1..N。初始的时候,所有的整数坐标点上均有一块金子,共N*N块。
    一阵风吹过,金子的位置发生了一些变化。细心的小Z发现,初始在(i,j)坐标处的金子会变到(f(i),fIj))坐标处。其中f(x)表示x各位数字的乘积,例如f(99)=81,f(12)=2,f(10)=0。如果金子变化后的坐标不在1..N的范围内,我们认为这块金子已经被移出游戏。同时可以发现,对于变化之后的游戏局面,某些坐标上的金子数量可能不止一块,而另外一些坐标上可能已经没有金子。这次变化之后,游戏将不会再对金子的位置和数量进行改变,玩家可以开始进行采集工作。
    小Z很懒,打算只进行K次采集。每次采集可以得到某一个坐标上的所有金子,采集之后,该坐标上的金子数变为0。
    现在小Z希望知道,对于变化之后的游戏局面,在采集次数为K的前提下,最多可以采集到多少块金子?
    答案可能很大,小Z希望得到对1000000007(10^9+7)取模之后的答案。

Input

  共一行,包含两介正整数N,K。

Output

  一个整数,表示最多可以采集到的金子数量。

Sample Input

1 2 5

Sample Output

18

HINT

N < = 10^12 ,K < = 100000

对于100%的测试数据:K < = N^2

Solution:

  看了大佬的博客:http://www.cnblogs.com/lidaxin/p/5234975.html

 

 1 #pragma GCC optimize("O3")
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <algorithm>
 6 #include <queue>
 7 using namespace std;
 8 #define mod 1000000007
 9 #define N 20050
10 #define M 15
11 long long n,k,num[N*10],size[N*10],ans;
12 struct NODE {
13     int x,y;
14     long long val;
15     NODE(int X=0,int Y=0) {x=X,y=Y,val=1ll*size[num[X]]*size[num[Y]];}
16     friend bool operator < (NODE a,NODE b) {return a.val<b.val;}
17 } ;
18 long long cnt,tmp[N*50],f[M][N*5][2];
19 int bit[M];
20 priority_queue <NODE> q;
21 bool cmp(int x,int y) {return size[x]>size[y];}
22 void dfs(int last,int len,long long now) {
23     if(len==bit[0]+1) {tmp[++cnt]=now; return ;}
24     if(!now) return ;
25     for(int i=last; i<=9; ++i) dfs(i,len+1,now*i);
26 }
27 int main() {
28     scanf("%lld%lld",&n,&k);
29     while(n) bit[++bit[0]]=n%10,n/=10;
30     dfs(0,0,1); tmp[++cnt]=0;
31     sort(tmp+1,tmp+cnt+1); cnt=unique(tmp+1,tmp+cnt+1)-tmp-1;
32     f[0][2][0]=1;
33     for(int i=0; i<=bit[0]; ++i) {
34         for(int j=1; j<=cnt; ++j) {
35             for(int h=0; h<=1; ++h) {
36                 if(f[i][j][h]) {
37                     for(int l=(i==0)?0:1; l<=9; ++l) {
38                         f[i+1][lower_bound(tmp+1,tmp+cnt+1,tmp[j]*l)-tmp][h+l>bit[i+1]]+=f[i][j][h];
39                     }
40                 }
41             }
42         }
43     }
44     for(int i=1; i<=cnt; ++i) {
45         num[i]=i;
46         for(int j=1; j<bit[0]; ++j) size[i]+=f[j][i][0]+f[j][i][1];
47         size[i]+=f[bit[0]][i][0];
48     } sort(num+2,num+cnt+1,cmp);
49     q.push(NODE(2,2));
50     for(int i=0; !q.empty(); ) {
51         NODE temp=q.top(); q.pop();
52         ans=(ans+temp.val)%mod;
53         ++i;
54         if(i>=k) break;
55         if(temp.x!=temp.y) {
56             ans=(ans+temp.val)%mod;
57             ++i;
58             if(i>=k) break;        
59         }
60         if(temp.x!=temp.y) q.push(NODE(temp.x+1,temp.y));  
61         if(temp.x==2) q.push(NODE(temp.x,temp.y+1));
62     } printf("%lld\\n",ans);
63     return 0;
64 }

 

 

 

以上是关于bzoj3131 [Sdoi2013]淘金的主要内容,如果未能解决你的问题,请参考以下文章

[BZOJ 3131][Sdoi2013]淘金

BZOJ 3131 SDOI2013 淘金 数位dp

bzoj千题计划268:bzoj3131: [Sdoi2013]淘金

淘金(bzoj 3131)

BZOJ 3131 淘金

[SDOI2013] 淘金