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;
}
不摆烂了,写题