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;
}

猜你喜欢

转载自www.cnblogs.com/ztz11/p/9885574.html