51nod1693

题解:

首先将问题转化,可以发现操作改为两种

一种是s*=k,代价为k,一种是s--,代价为1

转化成图论,spfa跑最短路

然后更据一些证明,代价1的k<=13且为质数,并且不可能操作2连续5次

所以就可以优化

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1000005,M=20000005;
int n,a[N],b[M],f[N],in[N],dis[N];
int main()
{
    scanf("%d",&n);
    f[0]=6;
    f[1]=2,f[2]=3,f[3]=5,f[4]=7,f[5]=11,f[6]=13;
    int l=0,r=1;
    memset(dis,0x3f,sizeof dis);
    dis[1]=0;
    b[0]=1;
    while (l!=r)
     {
         int now=b[l++];
         in[now]=0;
         l%=M;
         if (now!=1&&dis[now-1]>dis[now]+1)
          {
              dis[now-1]=dis[now]+1;
              if (!in[now-1])
               {
                   b[r++]=now-1;
                   in[now-1]=1;
                   r%=M;
               }
          }
         for (int i=1;f[i]*now<=n+10&&i<=f[0];i++)
          {
              int k=f[i]*now;
              if (dis[k]>dis[now]+f[i])
               {
                   dis[k]=dis[now]+f[i];
                   if (!in[k])
                    {
                        b[r++]=k;
                        in[k]=1;
                        r%=M;
                    }
               }
          }
     }
    printf("%d",dis[n]);
}
时间: 2024-10-14 04:28:34

51nod1693的相关文章

51nod1693 水群

QwX (题目提供者) 首先简化题目,题面的意思就是,当前有一个数s 操作1是s*=k代价为k,操作2是s--代价为1 求把s从1变到n的最小代价 做法1: 直接暴力记忆化搜索,F(i)表示从1到i用的最小操作数 则F(i)=min(F(i+1),min{F(k)+n/k|n%k==0}) 当然这样做肯定过不了 做法2: 考虑把问题转换成图论模型,对于每个i 连边i→i-1边权为1,连边i→i*k边权为k 那么题目就是要求点1到点n的最短路 但是很显然这样复杂度还是很高并不能过 做法3: 注意到