LuoguP3303 「SDOI2013」淘金

LuoguP3303 「SDOI2013」淘金

哇简单DP题!

这都能评黑?

考虑对于每个 (x)​ ,求出 (f(i)=x)​ 的 (i)​ 的个数,使用数位 DP ,由于 (x) 的质因子只可能有 2,3,5,7 四种,所以 (x) 的范围不会太大,数位 DP 记录已用格子数和每个质因子的指数即可。记其为 (c(x))

然后对 (c(x)) 从大到小排序,对每个点记录指针表示最大的可用点,用堆维护即可。

#include<bits/stdc++.h>
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fd(i,a,b) for(int i=a;i>=b;--i)
#include <ext/pb_ds/priority_queue.hpp>
using namespace __gnu_pbds;
#define ll long long
using namespace std;
const int N=1e5+10;
const int M=5e6+10;
const int mod=1e9+7;
ll n,f[20][41][30][20][20],c[M],ans;
int k,a[20],s1,s2,s3,s4,cnt;
bool flag=0;
struct node{
	ll x,y;
	inline bool operator<(const node &o)const{
		return x * c[y] < o.x * c[o.y];
	}
};
__gnu_pbds ::priority_queue< node > d;
bool cmp(ll a,ll b){return a>b;}
void add(ll &a,ll b){a=(a+b>=mod?a+b-mod:a+b);}
void trans(int t,int S1,int S2,int S3,int S4,int num,ll s,int type=1){
	while(!(num%2))++S1,num/=2;
	while(!(num%3))++S2,num/=3;
	while(!(num%5))++S3,num/=5;
	while(!(num%7))++S4,num/=7;
	if(type==-1){
		s1=S1;s2=S2;s3=S3;s4=S4;
		return;
	}
	f[t][S1][S2][S3][S4]+=s;
}
void dp(){
	int m=0;
	for(ll i=n;i;i/=10)a[++m]=i%10;
	fo(i,1,a[m]-1)trans(m,0,0,0,0,i,1);
	flag|=(a[m]==0);
	if(!flag)trans(m,0,0,0,0,a[m],1,-1);
	fd(i,m-1,1){
		fo(j1,0,39){
			fo(j2,0,25){
				fo(j3,0,17){
					fo(j4,0,14){
						ll tmp=f[i+1][j1][j2][j3][j4];
						if(!tmp)continue;
						fo(l,1,9){
							trans(i,j1,j2,j3,j4,l,tmp);
						}
					}
				}
			}
		}
		fo(l,1,9)
			trans(i,0,0,0,0,l,1);
		if(!flag)
			fo(l,1,a[i]-1)
				trans(i,s1,s2,s3,s4,l,1);
		flag|=(a[i]==0);
		if(!flag)trans(1,s1,s2,s3,s4,a[i],1,-1);
	}
	if(!flag)trans(1,s1,s2,s3,s4,1,1);
	fo(j1,0,39){
		fo(j2,0,25){
			fo(j3,0,17){
				fo(j4,0,14){
					ll tmp=f[1][j1][j2][j3][j4];
					if(tmp){
						c[++cnt]=tmp;
					}
				}
			}
		}
	}
}
void solve(){
	sort(c+1,c+cnt+1,cmp);
//	fo(i,1,cnt)printf("%d ",c[i]);
//	printf("
");
	fo(i,1,cnt)
		d.push((node){c[i],1});
	k=min((ll)k,(ll)cnt*cnt);
	fo(i,1,k){
		node a=d.top();
		d.pop();
		add(ans,a.x * c[a.y] % mod);
		if(a.y<cnt){
			d.push((node){a.x,a.y+1});
		}
	}
}
int main(){
	scanf("%lld%d",&n,&k);
	dp();
	solve();
	printf("%lld
",ans);
	
	return 0;
}
原文地址:https://www.cnblogs.com/Kelvin2005/p/15185180.html