P1052 [NOIP2005 提高组] 过河 题解(dp+数论优化)

题目链接

题目思路

这个有点毒瘤,主要是这个长度太长了

感觉就是距离太长其实答案不会有什么变化

假如你走p或者p-1步,gcd(p,p-1)=1;

而根据结论最大不能被p和p-1表示的点为p(p-1)-p-p+1 即p=10 len=71

所以把距离大于71的都当作71

//其实我也不太懂为啥能直接等价点玄学

还有如果s=t特判即可

代码

#include<bits/stdc++.h>
#define fi first
#define se second
#define debug cout<<"I AM HERE"<<endl;
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn=1e2+5,inf=0x3f3f3f3f,mod=1e9+7;
const int eps=1e-3;
int l,s,t,m;
int a[maxn],dis[maxn];
int vis[maxn*maxn],dp[maxn*maxn];
signed main(){
    scanf("%d",&l);
    scanf("%d%d%d",&s,&t,&m);
    for(int i=1;i<=m;i++){
        scanf("%d",&a[i]);
    }
    sort(a+1,a+1+m);
    if(s==t){ //只能走一步
        int ans=0;
        for(int i=1;i<=m;i++){
            ans+=(a[i]%s==0);
        }
        printf("%d\n",ans);
        return 0;
    }
    a[m+1]=l;
    for(int i=1;i<=m+1;i++){
        dis[i]=min(a[i]-a[i-1],71);
    }
    for(int i=1;i<=m+1;i++){
        a[i]=dis[i]+a[i-1];
        vis[a[i]]=1;
    }
    memset(dp,0x3f,sizeof(dp));
    dp[0]=0;
    for(int i=1;i<=a[m+1]+t-1;i++){
        for(int j=s;j<=t;j++){
            if(i-j<0) break;
            dp[i]=min(dp[i],dp[i-j]+vis[i]);
        }
    }
    int ans=inf;
    for(int i=a[m+1];i<=a[m+1]+t-1;i++){
        ans=min(ans,dp[i]);
    }
    printf("%d\n",ans);
    return 0;
}

不摆烂了,写题
原文地址:https://www.cnblogs.com/hunxuewangzi/p/14390122.html