ABC466F
Pure_ManaWing · · 题解
也许更好的阅读体验:个人博客。
分享一种比较小众的做法。
::::warning[闲话]{open} 第二次场切 F!!!而且这次瞪了 eps 秒就看出结论了。
观察题目可知,如果
发现这个式子没啥性质,尝试 dp。
设
我们最后需要求
如何去转移这个东西呢?以
定
对于剩下的区间
如果
综上,我们可以得到转移方程:
其中
边界处理:当我们
这个算法的时间复杂度是
把转移方程看作一棵树,应当是这样子:
我们发现只有右边的
考虑倒着处理
难点在如何证明时间复杂度是正确的。
::::success[处理单个
int val=b[i]-1,pos=i+1,res=0;
if(val<mb){res=1;}
else{
while(pos<=m){
if(val<mb){res++;break;}
int k;
if(b[pos]<=val)k=pos;
else{
int l=pos,r=m,ans=m+1;
while(l<=r){
int mid=(l+r)>>1;
if(b[mid]<=val){ans=mid;r=mid-1;}
else l=mid+1;
}
k=ans;
if(k==m+1)break;
}
int q=val/b[k];
res+=q*v[k];
val%=b[k];
if(!val){res++;break;}
pos=k+1;
}
if(val>0 && pos>m)res++;
}
v[i]=res;
::::
我们发现往下处理的时候,
对于
最后求
都看到这里了,还不点赞。
那还是人吗?
::::success[正确代码]
//#pragma GCC optimize("O3")
//#pragma GCC optimize("O2")
#include<bits/stdc++.h>
#define int long long
#define pb push_back
#define is insert
#define fr(i,a,b) for(int i=(a);i<=(b);i++)
#define rf(i,a,b) for(int i=(a);i>=(b);i--)
#define prq priority_queue
#define gYES cout << "YES\n"
#define gNO cout << "NO\n"
#define gYes cout << "Yes\n"
#define gNo cout << "No\n"
const int MOD=1000000007;
const int Mod=998244353;
const int N=2e5+5;
using namespace std;
int max(int ax,int ay){return ax>ay?ax:ay;}
int min(int ax,int ay){return ax<ay?ax:ay;}
int abss(int ax){return max(ax,-ax);}
void fastIO(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
}
int a[N],b[N],v[N],n,x,m=1;
void solve(){
cin>>n>>x;
fr(i,1,n)cin>>a[i];
b[1]=a[1];
fr(i,2,n)if(a[i]<b[m])b[++m]=a[i];
int mb=b[m]; v[m]=1;
rf(i,m-1,1){
int val=b[i]-1,pos=i+1,res=0;
if(val<mb){res=1;}
else{
while(pos<=m){
if(val<mb){res++;break;}
int k;
if(b[pos]<=val)k=pos;
else{
int l=pos,r=m,ans=m+1;
while(l<=r){
int mid=(l+r)>>1;
if(b[mid]<=val){ans=mid;r=mid-1;}
else l=mid+1;
}
k=ans;
if(k==m+1)break;
}
int q=val/b[k];
res+=q*v[k];
val%=b[k];
if(!val){res++;break;}
pos=k+1;
}
if(val>0 && pos>m)res++;
}
v[i]=res;
}
int c=x,ans=0;
fr(i,1,m){
if(c<b[i])continue;
int q=c/b[i];
ans+=q*v[i];
c%=b[i];
}
cout<<ans;
//以下为清空
m=1;
cout << "\n";
}
signed main(){
fastIO();
int t;cin>>t;
while(t--){
solve();
}
return 0;
}
::::