noip模拟80
A. 邻面合并
考场上别人一看都像是插头 \(dp\),之前没学,尽管这题不是插头,但是状压还是很容易看出的.
自己设的 \(dp\) 状态太烂了,只空间就需要三维,而且转移写起来还很麻烦.
别人可以想到用 \(0/1\) 表示开头,但是自己考场上却是咋也想不到.
最近很多自己想的 \(dp\) 都很烂,大部分都是因为很多没用的状态自己非要去枚举或者特判.
甚至自己一点儿 \(dp\) 技巧都没有.
A_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS {
#define ll int
#define ull unsigned ll
#define lf double
#define lbt(x) ((x)&(-(x)))
#define mp(x,y) make_pair(x,y)
#define lb lower_bound
#define ub upper_bound
#define Fill(x,y) memset(x,y,sizeof x)
#define Copy(x,y) memcpy(x,y,sizeof x)
#define File(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
inline ll read() {
ll w=0; bool cit=1; char ch;
while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
while(isdigit(ch)) w=(w<<3)+(w<<1)+(ch^48),ch=getchar();
return cit?w:-w;
}
} using namespace BSS;
const ll N=105,M=9,W=(1<<8)+25;
ll m,n,U,ans;
ll zt[N],num[W];
ll dp[N][W],cs[N][N];
auto check=[](ll x,ll s)->bool{
ll lst=0;
for(ll i=1;i<=m;i++){
if((!cs[x][i]) and ((s>>i-1)&1)) return 0;
if((s>>i-1)&1) lst=1;
if(!cs[x][i]) lst=0;
if(cs[x][i] and (!lst)) return 0;
}
return 1;
};
auto calc=[](ll x,ll s,ll t,ll pos)->bool{
for(ll i=pos;i<=m;i++){
if(((t>>i-1)&1)and(!cs[x-1][i])) return 0;
if(((s>>i-1)&1)and(!cs[x][i])) return 0;
if(cs[x][i]!=cs[x-1][i]) return 1;
if(((s>>i-1)&1)xor((t>>i-1)&1)) return 1;
if((!cs[x][i]) and (!cs[x-1][i])) return 0;
}
return 0;
};
auto unit=[](ll x,ll s,ll t)->ll{
ll res=0;
for(ll i=1;i<=m;i++){
if(((s>>i-1)&1) and ((t>>i-1)&1)) res+=calc(x,s,t,i);
else res+=((t>>i-1)&1);
}
// cout<<x<<' '<<s<<' '<<t<<' '<<res<<endl;
return res;
};
signed main(){
File(merging);
n=read(),m=read(),U=(1<<m)-1,ans=2e8;
for(ll i=1;i<=n;i++){
for(ll j=1;j<=m;j++) cs[i][j]=read();
}
Fill(dp,0x3f),dp[0][0]=0; ll res,cnt,flag,nowcnt;
for(ll i=1;i<=U;i++) num[i]=num[i&(i-1)]+1;
for(ll i=1;i<=n;i++){
for(ll j=0;j<=U;j++){
if(!check(i,j)) continue;
for(ll k=0;k<=U;k++){
if(!check(i-1,k)) continue;
dp[i][j]=min(dp[i][j],dp[i-1][k]+unit(i,k,j));
}
}
}
for(ll i=0;i<=U;i++) ans=min(ans,dp[n][i]);
printf("%d\n",ans),exit(0);
}
B. 光线追踪
一看就是线段树,自己还是想得麻烦了.
可以选择开两棵线段树,但是自己却非要维护斜率,维护的还是错的.
B_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS {
#define ll long long
#define ull unsigned ll
#define lf long double
#define lbt(x) ((x)&(-(x)))
#define mp(x,y) make_pair(x,y)
#define lb lower_bound
#define ub upper_bound
#define Fill(x,y) memset(x,y,sizeof x)
#define Copy(x,y) memcpy(x,y,sizeof x)
#define File(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
inline ll read() {
ll w=0; bool cit=1; char ch;
while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
while(isdigit(ch)) w=(w<<3)+(w<<1)+(ch^48),ch=getchar();
return cit?w:-w;
}
} using namespace BSS;
#define ls (x<<1)
#define rs (x<<1|1)
const ll N=2e5+21,inf=1e10;
const lf eps=1e-8;
ll m,n,ops,cnt,ansxx,ansyy;
lf lsh[N<<2];
struct I { ll opt; lf x0,y0,x2,y2; } q[N];
struct II { ll w[2]; } tr[N<<2];
auto zz=[](lf x)->bool{ return x-eps<=0 and x+eps>=0; };
auto slope=[](ll x,ll y)->lf{ return zz(x) ? inf : 1.0*y/((lf)x); };
auto comp=[](ll i,ll j,ll op)->ll{
if(!(i and j)) return i+j;
if(op){
if(q[i].y0==q[j].y0) return max(i,j);
return ( (q[i].y0<q[j].y0) ? i : j ) ;
}
if(q[i].x0==q[j].x0) return max(i,j);
return ( (q[i].x0<q[j].x0) ? i : j );
};
void update(ll x,ll l,ll r,ll ql,ll qr,ll id,ll op){
if(ql>qr) return ;
if(l>=ql and r<=qr){
tr[x].w[op]=comp(tr[x].w[op],id,op);
// if(tr[x].w[op]==2 and id==2) cout<<l<<' '<<r<<' '<<ql<<' '<<qr<<' '<<lsh[l]<<' '<<lsh[r]<<' '<<id<<' '<<op<<" der\n";
return ;
}
ll mid=(l+r)>>1;
if(ql<=mid) update(ls,l,mid,ql,qr,id,op);
if(qr>mid) update(rs,mid+1,r,ql,qr,id,op);
}
ll query(ll x,ll l,ll r,ll qpos,ll op){
// cout<<"x:"<<x<<' '<<qpos<<' '<<l<<' '<<r<<' '<<lsh[l]<<' '<<lsh[r]<<' '<<op<<' '<<tr[x].w[op]<<endl;
if(l==r) return tr[x].w[op]; ll mid=(l+r)>>1,res;
res= ( qpos<=mid ? query(ls,l,mid,qpos,op) : query(rs,mid+1,r,qpos,op) );
return comp(res,tr[x].w[op],op);
}
signed main(){
File(raytracing);
ops=read(); lf x0,y0,x2,y2,sp1,sp2,sp3,p1,p2,p3; ll ansx,ansy,opt;
for(ll i=1;i<=ops;i++){
q[i].opt=read();
if(q[i].opt&1){
x0=read(),y0=read(),x2=read(),y2=read();
q[i].x0=x0,q[i].y0=y0,q[i].x2=x2,q[i].y2=y2;
lsh[++cnt]=slope(x0,y0),lsh[++cnt]=slope(x0,y2),lsh[++cnt]=slope(x2,y0);
}
else{
q[i].x0=read(),q[i].y0=read();
lsh[++cnt]=slope(q[i].x0,q[i].y0);
}
}
sort(lsh+1,lsh+1+cnt),cnt=unique(lsh+1,lsh+1+cnt)-lsh-1,n=cnt;
// cout<<"lsh: "; for(ll i=1;i<=n;i++) cout<<lsh[i]<<' '; puts("");
for(ll i=1;i<=ops;i++){
if(q[i].opt&1){
x0=q[i].x0,y0=q[i].y0,x2=q[i].x2,y2=q[i].y2;
if(!x0) ansyy=comp(ansyy,i,1);
if(!y0) ansxx=comp(ansxx,i,0);
sp1=slope(x2,y0),sp2=slope(x0,y0),sp3=slope(x0,y2);
p1=lb(lsh+1,lsh+1+cnt,sp1)-lsh;
p2=lb(lsh+1,lsh+1+cnt,sp2)-lsh;
p3=lb(lsh+1,lsh+1+cnt,sp3)-lsh;
// cout<<sp1<<' '<<sp2<<' '<<sp3<<' '<<p1<<' '<<p2<<' '<<p3<<" skr\n";
update(1,1,n,p1,p2,i,1); // 1 表示 y
update(1,1,n,p2,p3,i,0); // 0 表示 x
}
else{
sp1=slope(q[i].x0,q[i].y0),p1=lb(lsh+1,lsh+1+cnt,sp1)-lsh;
if(sp1==0) { printf("%lld\n",ansxx); continue; }
if(sp1==inf) { printf("%lld\n",ansyy); continue; }
ansx=query(1,1,n,p1,0),ansy=query(1,1,n,p1,1);
y0=1.0*q[ansx].x0*q[i].y0/(1.0*q[i].x0);
if(!(ansx and ansy)) printf("%lld\n",ansx+ansy);
else{
if(y0==q[ansy].y0) printf("%lld\n",max(ansx,ansy));
else printf("%lld\n",((y0<q[ansy].y0)?ansx:ansy));
}
}
}
exit(0);
}
/*
3
1 2 3 4 7
1 3 5 8 10
2 4 3
*/
C. 百鸽笼
C_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS {
#define ll long long
#define ull unsigned ll
#define lf long double
#define lbt(x) ((x)&(-(x)))
#define mp(x,y) make_pair(x,y)
#define lb lower_bound
#define ub upper_bound
#define Fill(x,y) memset(x,y,sizeof x)
#define Copy(x,y) memcpy(x,y,sizeof x)
#define File(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
inline ll read() {
ll w=0; bool cit=1; char ch;
while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
while(isdigit(ch)) w=(w<<3)+(w<<1)+(ch^48),ch=getchar();
return cit?w:-w;
}
} using namespace BSS;
const ll N=32,mod=998244353;
ll m,n,sum;
ll pre[N],val[N],ans[N],frc[N*N],inv[N*N];
ll g[N][N*N],f[N][N*N],C[N*N][N*N];
auto ksm=[](ll a,ll b,ll c)->ll{
a%=c; ll w=1;
for(;b;b>>=1,a=a*a%c) if(b&1) w=w*a%c;
return w%c;
};
signed main(){
File(c);
n=read();
for(ll i=1;i<=n;i++) pre[i]=pre[i-1]+(val[i]=read());
frc[0]=1,frc[1]=1,inv[1]=1;
for(ll i=2;i<=pre[n];i++) frc[i]=frc[i-1]*i%mod,inv[i]=(mod-mod/i)*inv[mod%i]%mod;
for(ll i=0;i<=pre[n];i++){
C[i][0]=1;
for(ll j=1;j<=i;j++){
C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
}
}
g[0][0]=1;
for(ll i=1;i<=n;i++){
pre[i]=pre[i-1]+val[i]-1;
for(ll j=i;j>0;j--)
for(ll k=pre[n];k>=0;k--)
for(ll h=0;h<val[i] and h<=k;h++)
g[j][k]=(g[j][k]-g[j-1][k-h]*C[k][h]%mod+mod)%mod;
}
for(ll i=1;i<=n;i++){
Copy(f,g);
for(ll j=1;j<n;j++){
for(ll k=0;k<=pre[n]-val[i]+1;k++){
for(ll h=0;h<val[i] and h<=k;h++)
f[j][k]=(f[j][k]+f[j-1][k-h]*C[k][h]%mod)%mod;
}
}
for(ll j=0;j<n;j++){
for(ll k=0;k<=pre[n]-val[i]+1;k++){
// cout<<f[j][k]<<' ';
ans[i]=(ans[i]+f[j][k]*C[k+val[i]-1][k]%mod*ksm(inv[j+1],k+val[i],mod)%mod)%mod;
}
// puts("");
}
}
for(ll i=1;i<=n;i++) printf("%lld ",ans[i]);
exit(0);
}
D. 滑稽树下你和我
\(Yubai\) 画了漂漂亮亮美美丽丽的图,建议去欣赏.
D_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS {
#define ll long long
#define ull unsigned ll
#define lf long double
#define lbt(x) ((x)&(-(x)))
#define mp(x,y) make_pair(x,y)
#define lb lower_bound
#define ub upper_bound
#define Fill(x,y) memset(x,y,sizeof x)
#define Copy(x,y) memcpy(x,y,sizeof x)
#define File(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
inline ll read() {
ll w=0; bool cit=1; char ch;
while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
while(isdigit(ch)) w=(w<<3)+(w<<1)+(ch^48),ch=getchar();
return cit?w:-w;
}
} using namespace BSS;
const ll N=2e3+21,inf=1e10;
const lf eps=1e-8;
lf ans;
ll m,n,ts,cnt,sx,sy;
ll d[N],xi[N],yi[N],head[N];
ll vis[N][N];
lf dis[N][N],f[N][N];
struct I {
ll u,v; lf w;
I(){}
I(ll u_,ll v_,lf w_) : u(u_),v(v_),w(w_) {}
friend bool operator < (I i,I j){
return i.w>j.w;
}
};
struct II { ll u,v,nxt; } e[N<<1];
struct III { ll u,v; } o[N];
priority_queue<I> que;
auto add=[](ll u,ll v)->void{
e[++ts].u=u,e[ts].v=v,e[ts].nxt=head[u];
head[u]=ts,d[u]++;
};
auto zz=[](lf w)->lf{ return (w-eps<=0 and w+eps>=0) ? 0 : w ; };
auto calc=[](ll i,ll j)->lf{
return sqrt(1.0*(xi[i]-xi[j])*(xi[i]-xi[j])+1.0*(yi[i]-yi[j])*(yi[i]-yi[j]));
};
auto love=[](pair<lf,lf> i,pair<lf,lf> j)->lf{
return i.first*j.first+i.second*j.second;
};
auto solve=[](ll i,ll j)->lf{
ll u=o[j].u,v=o[j].v;
pair<lf,lf> ab=mp(xi[v]-xi[u],yi[v]-yi[u]),ac=mp(xi[i]-xi[u],yi[i]-yi[u]);
lf w=love(ab,ac)/calc(u,v);
if(w<0 or w>calc(u,v)) return min(calc(i,u),calc(i,v));
return sqrt(calc(i,u)*calc(i,u)-w*w);
};
signed main(){
File(tree);
n=read(),cnt=n,sx=read(),sy=read(); ll u,v;
for(ll i=1;i<=n;i++) xi[i]=read(),yi[i]=read();
for(ll i=2;i<=n;i++){
u=read(),v=read(),o[++cnt].u=u,o[cnt].v=v;
add(u,cnt),add(cnt,u),add(v,cnt),add(cnt,v);
}
ans=1e15;
for(ll i=1;i<=n;i++){
for(ll j=i;j<=n;j++) dis[i][j]=calc(i,j),dis[j][i]=dis[i][j];
for(ll j=n+1;j<=cnt;j++) dis[i][j]=solve(i,j),dis[j][i]=dis[i][j];
}
for(ll i=1;i<=cnt;i++){
for(ll j=1;j<=cnt;j++) f[i][j]=inf;
}
// for(ll i=1;i<=n;i++){
// for(ll j=1;j<=cnt;j++) cout<<dis[i][j]<<' ';
// puts("");
// }
// puts("");
// que.push(mp(sx,sy)); pair<ll,ll> x;
f[sx][sy]=dis[sx][sy];
I x; que.push(I(sx,sy,f[sx][sy]));
while(que.size()){
x=que.top(),que.pop(),u=x.u,v=x.v;
if(vis[u][v]) continue; vis[u][v]=1;
for(ll i=head[u];i;i=e[i].nxt){
if(f[e[i].v][v]>max(f[u][v],dis[e[i].v][v])){
f[e[i].v][v]=max(f[u][v],dis[e[i].v][v]);
que.push(I(e[i].v,v,f[e[i].v][v]));
}
}
for(ll i=head[v];i;i=e[i].nxt){
if(f[u][e[i].v]>max(f[u][v],dis[u][e[i].v])){
f[u][e[i].v]=max(f[u][v],dis[u][e[i].v]);
que.push(I(u,e[i].v,f[u][e[i].v]));
}
}
}
// for(ll i=1;i<=n;i++){
// printf("%.5Lf\n",f[i][i]);
// }
// for(ll i=1;i<=n;i++){
// for(ll j=1;j<=n;j++) printf("%Lf ",f[i][j]);
// puts("");
// }
for(ll i=1;i<=n;i++){
if(d[i]>1) continue;
for(ll j=1;j<=n;j++){
if(d[j]>1) continue; ans=min(ans,min(f[i][j],f[j][i]));
}
}
printf("%.6Lf\n",ans),exit(0);
}