【ural 1223】 Chernobyl' Eagle on a Roof 題解
阿新 • • 發佈:2020-10-07
URAL-1223 Chernobyl’ Eagle on a Roof 題解
詳細的題解、dp優化的個人理解和解釋可以見我的這一篇文章
本文僅用於存放AC的程式碼以供參考。
O(k*n^2) 無優化dp
#include <cstdio> #include <algorithm> #include <cstring> using namespace std; typedef long long ll; #define REG register #define rep(i,a,b) for(REG int i=a;i<=b;i++) #define Rep(i,a,b) for(REG int i=a;i>=b;i--) const int INF=1e9; int N,K,f[20][1010]; inline int log2(int x){ int l=1,r=x,c=0; while(l<=r){ int mid=(l+r)>>1; c++; if(r-mid>mid-l) l=mid+1; else r=mid-1; } return c; } int main(){ while(1){ scanf("%d%d",&K,&N); if(K==N&&K==0) break; if(K>log2(N)){ printf("%d\n",log2(N)); continue; } memset(f,0,sizeof(f)); rep(i,1,N) f[1][i]=i; rep(i,2,K){ rep(j,1,N){ f[i][j]=INF; rep(w,1,j) f[i][j]=min(f[i][j],max(f[i-1][w-1],f[i][j-w])+1); } } printf("%d\n",f[K][N]); } return 0; }
O(KNlogN) 二分優化dp
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int INF=1e9,K=20,N=1010; inline int log2(int x){ int l=1,r=x,c=0; while(l<=r){ int mid=(l+r)>>1; c++; if(r-mid>mid-l) l=mid+1; else r=mid-1; } return c; } int k,n,a[2][N]; int main(){ while(scanf("%d%d",&k,&n)==2){ if(k+n==0) break; int t=log2(n); if(k>=t){ printf("%d\n",t); continue; } int *p=a[0],*f=a[1]; for(int i=1;i<=n;i++) f[i]=i; for(int i=2;i<=k;i++){ swap(p,f); for(int j=1;j<=n;j++) f[j]=0; f[1]=1; for(int j=2;j<=n;j++){ t=log2(j); if(i>=t){ f[j]=t; continue; } int l=1,r=j,mid,ans=r; while(l<=r){ mid=(l+r)>>1; if(p[mid-1]>=f[j-mid]) ans=mid,r=mid-1; else l=mid+1; } f[j]=max(p[ans-1],f[j-ans])+1; if(--ans>=1) f[j]=min(f[j],max(p[ans-1],f[j-ans])+1); } } printf("%d\n",f[n]); } return 0; }
O(KN)線性優化
這裡是沒有開long long的必要的,但是我懶得改了。
#include <cstdio> #include <algorithm> #include <vector> using namespace std; typedef long long ll; inline ll log2(ll x){ ll l=1,r=x,c=0; while(l<=r){ ll mid=(l+r)>>1; c++; if(r-mid>mid-l) l=mid+1; else r=mid-1; } return c; } vector<ll> f,p; int main(){ while(1){ ll k,n; scanf("%lld%lld",&k,&n); if(k+n==0) break; if(k>=log2(n)){ printf("%lld\n",log2(n)); continue; } f.resize(n+1); for(ll i=1;i<=n;i++) f[i]=i; for(ll i=2;i<=k;i++){ f.swap(p); f.resize(n+1); ll pre=0; f[1]=1; for(ll j=2;j<=n;j++){ if(max(f[pre],p[j-pre-1])+1==f[j-1]) f[j]=f[j-1]; else f[j]=f[j-1]+1,pre=j-1; } } printf("%lld\n",f[n]); } return 0; }
可以過1e18大資料的演算法
#include <cstdio>
#include <cmath>
using namespace std;
typedef long long ll;
#define REG register
#define rep(i,a,b) for(REG int i=a;i<=b;i++)
#define Rep(i,a,b) for(REG int i=a;i>=b;i--)
inline char getc(){
static char buf[1<<14],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<14,stdin),p1==p2)?EOF:*p1++;
}
inline ll scan(){
REG ll x=0; REG char ch=0;
while(ch<48) ch=getc();
while(ch>=48) x=x*10+ch-48,ch=getc();
return x;
}
inline ll log2(ll x){
ll l=1,r=x,mid,c=0;
while(l<=r){
mid=(l+r)>>1; c++;
if(mid-l>r-mid) r=mid-1;
else l=mid+1;
}
return c;
}
const ll F=2e6,K=60,N=1e18;
ll f[K+1][F],end[K+1];
inline void prework(){
rep(i,1,F-200) f[1][i]=i;
rep(i,1,F-200){
rep(j,2,K){
if(end[j]) break;
f[j][i]=f[j][i-1]+f[j-1][i-1]+1;
if(f[j][i]>=N) end[j]=i;
}
}
}
int main(){
//REG int T=scan();
prework();
while(1){
REG ll k=scan(),n=scan(),temp;
if(n+k==0) break;
if(k==1){ printf("%lld\n",n); continue; }
if(k==2){
ll t=floor(sqrt(n<<1));
if(t*(t+1)<n<<1) t++;
printf("%lld\n",t); continue;
}
temp=log2(n);
if(k>=temp){ printf("%lld\n",temp); continue; }
REG int l=1,r=end[k],mid,ans;
while(l<=r){
mid=(l+r)>>1;
if(f[k][mid]>=n) r=mid-1,ans=mid;
else l=mid+1;
}
printf("%d\n",ans);
}
return 0;
}