源文件在我的网盘上。
(只有机智的人才能看到我的链接)
机智的双重下划线~~~
T1
T1就是一个递推,这题目把我恶心到了。。。用double即可。上 代码。
#include <cstring> #include <cstdio> int n,i,j,k,m,l,t,v,u,s,d; int coml[2000],comr[2000],man; double mat[2000][2000],mat2[2000],mat3[2000],ma; #define ubit 0xffffffff int main(){ freopen("elimination.in","r",stdin); freopen("elimination.out","w",stdout); scanf("%d",&n); m=1<<n; for(i=0;i<m;++i){ mat2[i]=1.0; coml[i]=i^1; comr[i]=i^1; for(j=0;j<m;++j){ scanf("%d",&k); mat[i][j]=(k+0.0)/100; } } for(i=1;i<=n;++i){ u=1<<i; t=(ubit>>(i+1))<<(i+1); for(j=0;j<m;++j){ mat3[j]=0.0; for(k=coml[j];k<=comr[j];++k){ mat3[j]+=mat2[k]*mat[j][k]; } mat3[j]*=mat2[j]; l=coml[j]&t; if(u&coml[j]){ coml[j]=l; comr[j]=l+u-1; }else{ l|=u; coml[j]=l; comr[j]=l+u-1; } } for(j=0;j<m;++j){ mat2[j]=mat3[j]; } } ma=mat2[0]; for(i=1;i<m;++i){ if(mat2[i]>ma){ ma=mat2[i]; man=i; } } printf("%d ",man+1); return 0; }
T2
差分约束系统。。。调得我快Shit了(然后。。我会告诉你我还没过么?)
上 代码。
#include <cstdio> #include <cstring> #define lowbit(x) (x&-x) int next[40000],to[40000],f[40000],len[40000],head[40000],hl,i,j,k,h; int ip,a,b,c,pp[40000],ppl,n; inline void addEdge(int f,int t,int w){ ++hl; next[hl]=head[f]; to[hl]=t; len[hl]=w; head[f]=hl; } int q[400000],qt,qh; bool iq[40000]; void spfa(){ memset(f,0x7f,sizeof f); qh=0; qt=1; iq[n+1]=1; q[0]=n+1; f[n+1]=0; while(qh!=qt){ a=q[qh]; //printf("( %d ):#%d ",qh,a); iq[a]=0; for(b=head[a];b!=0;b=next[b]){ //printf("Access #%d: pre dist %d , suf dist %d ",to[b],f[to[b]],f[a]+len[b]); if(f[a]+len[b]<f[to[b]]){ //printf("Relax #%d ",to[b]); f[to[b]]=f[a]+len[b]; if(!iq[to[b]]){ iq[to[b]]=true; q[qt++]=to[b]; } } } ++qh; } } int main(){ freopen("trees.in","r",stdin); freopen("trees.out","w",stdout); scanf("%d%d",&n,&h); //printf("1 "); for(i=0;i<h;++i){ scanf("%d%d%d",&a,&b,&c); addEdge(b,a-1,-c); } //printf("2 "); for(i=0;i<=n;++i) addEdge(n+1,i,0); for(i=0;i<n;++i){ addEdge(i,i+1,1); addEdge(i+1,i,0); } spfa(); a=0x7fffffff; for(i=0;i<=n;++i) if(f[i]<a) a=f[i]; for(i=0;i<=n;++i) f[i]-=a; printf("%d ",f[n]); return 0; }
T3
一道机智的二分题目
先二分答案,再用DP检测答案是否可以。符合单调性(废话)。
DP方程:
$Fleft[ i,j ight] =max left{leftlfloor frac{s-kcdot a_i}{b_i} ight floor +Fleft[ i-1,j-k ight] forall k in left[ 0,minleft{ leftlfloor frac{s}{a_i} ight floor ,j ight} ight] ight}$
//上代码 #include <cstdio> #include <cstring> int n,m,i,j,k,l,r,ans,mid,t; int p[1000][2],f[2][1000]; int now,pp,t2; bool dp(int s){ memset(f,-1,sizeof f); now=0,pp=1; f[0][0]=0; for(i=0;i<n;++i){ now = pp^now; pp = pp^now; now = pp^now; for(j=0;j<=m;++j){ t=s/p[i][0]; t=t<j?t:j; for(k=0;k<=t;++k){ if(f[pp][j-k]!=-1){ t2=(s-k*p[i][0])/p[i][1]+f[pp][j-k]; f[now][j]=(f[now][j]<t2?t2:f[now][j]); } } } } return f[now][m]>=m; } int main(){ freopen("software.in","r",stdin); freopen("software.out","w",stdout); scanf("%d%d",&n,&m); for(i=0;i<n;++i){ scanf("%d%d",p[i],p[i]+1); } l=0,r=0x7fffffff; while(l<=r){ if(dp(mid=(l+r)/2)){ ans=mid; r=mid-1; }else{ l=mid+1; } } printf("%d ",ans); return 0; }