CF2091G dp *2300
\[\begin{flalign*}
&题意:给定s和k,起点0,初始向右,步长k,每次转向步长变为max(1,k-1)\\&
问恰好到达s时最大步长&\\&
显然s>=k^2时必然有解,max(k-2,1)\\&
初始会剩下s\ mod \ k的长度,然后转向,相当于模意义上的加1,由于上一次能走k步\\&
那么必然能取完剩余系让余数被k-2整除\\&
剩下来的是s\le 1e6的时候该如何求解,考虑dp\\&
dp_{i,k}代表步长为i的时候是否能到达k\\&
可以考虑调和级数枚举+可变长bitset优化dp做到O(SklogS/64)\\&
或者直接倒序枚举进行dp,转移为:\\&
dp[i][j]=dp[i][j-i]|dp[i+1][j-i]
\end{flalign*}
\]
#include<tr2/dynamic_bitset>
using std::tr2::dynamic_bitset;
void solve(){
int s;
cin>>s>>k;
if(s>=k*k){
if(s%k==0) cout<<k<<endl;
else cout<<max(1ll,k-2)<<endl; return;
}
vector<dynamic_bitset<>>dp(k+1);
for(int i=0;i<=k;i++) dp[i].resize(s+1);
for(int j=0;j<=s;j+=k) dp[k][j]=1;
for(int i=k-1,cnt=0;i>=1;i--,cnt++){
if(dp[i+1][s]) return cout<<i+1<<endl,void();
if(cnt&1)
for(int j=0;j<=s;j+=i){
dp[i]|=(dp[i+1]<<=i);
}
else
for(int j=s;j>=0;j-=i){
dp[i]|=(dp[i+1]>>=i);
}
}
cout<<1<<endl;
}

浙公网安备 33010602011771号