20181031noip模拟赛T2
思路:
这道题是个图论抽象的题目……
考场上想到了没写对……
我们发现,f函数转移的方式有两种,要么是代价10的+1,要么是代价1的乘一个质因数
那么我们就可以将这个抽象为一张图
每个i向每个i+1连一条边权为10的边
每个i向每个i*质因子[j]连一条边权为1的边
跑最短路即可
跑完最短路就是状压搜索
加上最优化剪枝和记忆化剪枝即可
代码:
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #define rii register int i #define rij register int j #define int long long using namespace std; int k,dp[100005]; int ans,sl,ss[10005],sk,s[10005],minx,head[505],cnt,jl[505]; int fin=2147483647,dis[105]; struct uio{ int nxt,to,val; }x[10005]; void add(int from,int to,int val) { cnt++; x[cnt].to=to; x[cnt].val=val; x[cnt].nxt=head[from]; head[from]=cnt; } //void dfs(int p,int q,int dj,int sd) //{ // if(sd>100) // { // return; // } // if(dj>ans) // { // return; // } // if(q==0) // { // ans=min(ans,dj); // return; // } // dfs(p,(q+1)%p,dj+10,sd+1); // for(rii=1;i<=sl;i++) // { // dfs(p,(q*s[i])%p,dj+1,sd+1); // } //} void djstl(int wz) { for(rii=head[wz];i!=0;i=x[i].nxt) { if(dis[x[i].to]>dis[wz]+x[i].val) { dis[x[i].to]=dis[wz]+x[i].val; djstl(x[i].to); } } } void cf(int val) { cnt=0; memset(head,0,sizeof(head)); sl=0; for(rii=2;i<=val;i++) { if(val%i==0) { val/=i; if(s[sl]!=i) { sl++; s[sl]=i; i--; } } if(val==1) { return; } } } int f(int val) { cnt=0; memset(x,0,sizeof(x)); memset(head,0,sizeof(0)); memset(dis,0x3f,sizeof(dis)); int p=0,q=1,ltt=val; while(ltt>0) { p+=ltt%10; ltt/=10; } p+=5; ltt=val; while(ltt>0) { q*=ltt%10; ltt/=10; } cf(val); q+=233; q%=p; for(rii=0;i<p;i++) { for(rij=1;j<=sl;j++) { add(i,i*s[j]%p,1); } add(i,(i+1)%p,10); } dis[q]=0; djstl(q); return dis[0]; } void cfk(int val) { sk=0; for(rii=2;i<=val;i++) { if(val%i==0) { val/=i; if(ss[sk]!=i) { sk++; ss[sk]=i; i--; } } if(val==1) { return; } } } inline int gtv(int v) { int kkk=1,cnt=0; while(v!=0) { cnt++; if(v%2==1) { kkk*=ss[cnt]; } v/=2; } return kkk; } void kfs(int zt,int dj) { if(dp[zt]>dj) { dp[zt]=dj; } else { return; } if(dj>=fin) { return; } if(dj<fin&&zt==(1<<sk)-1) { fin=dj; return; } for(rii=1;i<=(1<<sk)-1;i++) { if((zt&i)==0) { kfs(zt|i,dj+f(gtv(i))); } } } signed main() { freopen("k.in","r",stdin); freopen("k.out","w",stdout); memset(dp,0x3f,sizeof(dp)); cin>>k; cfk(k); if(sk==0) { cout<<f(k); return 0; } fin=f(k); kfs(0,0); cout<<fin; }