P3303 [SDOI2013] 淘金

是个简单题,可惜我代码暂时写挂了,起床再来改()

显然先要求出 cnt(f(i)),(i[1,N]),cnt(x) 表示 x 的出现次数。求出来之后两两相乘贪心即可。

f(i) 最大可能是 1012 ,省略掉了大于 N 的情况。所以要探讨下 f(i) 的不同取值数量。

map<ll,bool>mp; map<pair<int,ll>,bool>vis; int tot=0; void dfs(int x,ll num) { if(vis[make_pair(x,num)]) return ; if(x==13) { if(!mp[num]) mp[num]=1,++tot; return ; } for(int i=1;i<=9;i++) dfs(x+1,num*i); vis[make_pair(x,num)]=1; } int main() { dfs(1,1); cout<<tot+1; //+1是因为还有1e12 }

打表发现有 8282 种可能。

考虑求出 cnt(f(i)) ,这个枚举下之后数位 dp 即可,即枚举 f(i),然后考虑找一堆一些数使得乘积为 f(i),这里直接转化为找到一些数,使得这些数各位都是 f(i) 的因数。用 f[x][id] 表示当前第 x 位,目前剩余的数是 map[id] 的答案,对于边界,当且仅当 map[id]=1 时能有贡献。

Code

#include <bits/stdc++.h> #define ll long long using namespace std; int rd() { int f=1,sum=0; char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)) {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();} return sum*f; } ll lrd() { ll f=1,sum=0; char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)) {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();} return sum*f; } const int mod=(int)(1e9+7); unordered_map<ll,int>mp; ll f[15][8300]; ll a[8300],acnt[8300]; int num[15],tot,cnt; ll n,m; ll dfs(int lim,int x,int id) { if(!x) return a[id]==1; if(!lim&&~f[x][id]) return f[x][id]; // cout<<x<<" "<<id<<endl; int nex=lim?num[x]:9; ll res=0; for(int i=1;i<=nex;i++) if(a[id]%i==0) res+=dfs(lim&(i==nex),x-1,mp[a[id]/i]); if(!lim) f[x][id]=res; return res; } namespace xgf { unordered_map<ll,bool>vis[14]; void dfs(int x,ll number) { if(vis[x].count(number)) return ; if(x==13) { if(!mp[number]) a[++cnt]=number,mp[number]=1; return ; } for(int i=1;i<=9;i++) dfs(x+1,number*i); vis[x][number]=1; } } bool cmp(ll x,ll y) { return x>y; } priority_queue<ll>q; int main() { n=lrd(); m=lrd(); ll x=n; while(x) num[++tot]=x%10,x/=10; xgf::dfs(1,1); a[++cnt]=(ll)(1e12),mp[a[cnt]]=cnt; sort(a+1,a+1+cnt); for(int i=1;i<=cnt;i++) mp[a[i]]=i; memset(f,-1,sizeof(f)); for(int i=1;i<=cnt;i++) { if(a[i]>n) { cnt=i-1; break; } for(int j=1;j<=tot;j++) acnt[i]+=dfs(j==tot,j,i); // cout<<a[i]<<" "<<acnt[i]<<endl; } ll ans=0,qwq=sqrt(m); sort(acnt+1,acnt+1+cnt,cmp); for(int i=1;i<=min(1ll*cnt,qwq*4);i++) { for(int j=1;j<=min(1ll*cnt,qwq*4);j++) { if(q.size()<m) q.push(-1ll*acnt[i]*acnt[j]); else if(-q.top()<acnt[i]*acnt[j]) q.pop(),q.push(-1ll*acnt[i]*acnt[j]); } } // cout<<q.size()<<endl; while(!q.empty()) (ans+=-1ll*q.top())%=mod,q.pop(); printf("%lld",ans); return 0; }

__EOF__

本文作者F x o r G
本文链接https://www.cnblogs.com/xugangfan/p/15872345.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   FxorG  阅读(52)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示