清北考前刷题da7下午好
三向城
/* 原图一定是一棵完全二叉树。 根节点是x,左节点是x*2,右节点是x*2+1 转化为二进制往左右走就很明显了。 */ #include<iostream> #include<cstdio> #include<cstring> #define ll long long using namespace std; int T,x,y,k,ans,pos; inline int read() { int x=0,f=1;char c=getchar(); while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } int main() { freopen("city.in","r",stdin); freopen("city.out","w",stdout); T=read(); while(T--) { x=read();y=read();ans=0; if(x==y){printf("1\n");continue;} while(x!=y) { if(x>y) x/=2,ans++; if(y>x) y/=2,ans++; } printf("%d\n",ans); } return 0; }
灵魂画师
/* dp[i][j][k]表示第i个元素经过j次染色变为k颜色的概率。 考虑一段区间,每个元素只有选和不选两个状态,所以概率都为1/2. 转移的时候枚举下一个染不染和染成什么颜色。染成下一种颜色的概率是1/c。 可以看出第一维是没有用的,因为被覆盖次数相同的格子概率是相同的。 */ #include<iostream> #include<cstdio> #include<cstring> #define N 107 using namespace std; int n,m,tot,c,k,t,l,r,cnt[N]; double dp[N][N],ans; inline int read() { int x=0,f=1;char c=getchar(); while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } void DP() { dp[0][1]=1; for(int i=0;i<tot;i++) { for(int j=0;j<c;j++) { dp[i+1][j]+=dp[i][j]/2; for(int x=0;x<c;x++) dp[i+1][(j*x)%c]+=dp[i][j]/(2*c); } } for(int i=1;i<=n;i++) for(int j=0;j<c;j++) ans+=dp[cnt[i]][j]*j; printf("%.3lf\n",ans); } int main() { freopen("paint.in","r",stdin); freopen("paint.out","w",stdout); n=read();c=read();k=read(); for(int i=1;i<=k;i++) { l=read();r=read(); for(int j=l;j<=r;j++) cnt[j]++,tot=max(tot,cnt[j]); }DP(); return 0; }
香子兰
#include <cstdio> #define inf 1000000007 #define N 24 int a[N][N],d[N][N],f[2][N][1050000],e[N],cnt[1050000]; int n,n1,n2,x,y,z,i,j,m,k,q,ans,sta; int main() { freopen("vanilla.in", "r", stdin); freopen("vanilla.out", "w", stdout); e[0] = 1; //预处理2^i for (i=1; i<=22; ++i) e[i] = e[i-1]<<1; //预处理每个二进制数中有几个1 for (i=0; i<e[20]; ++i) for (x=i; x!=0; x>>=1) cnt[i] += x&1; scanf("%d%d", &n, &m); for (i=1; i<=n; ++i) for (j=1; j<=n; ++j) d[i][j] = inf*(i!=j); for (i=1; i<=m; ++i) { scanf("%d%d%d", &x, &y, &z); ++x;++y; if (z<d[x][y]) d[x][y] = d[y][x] = z; } // floyd求两两最短路 for (k=1; k<=n; ++k) for (i=1; i<=n; ++i) for (j=1; j<=n; ++j) if (d[i][k]+d[k][j] < d[i][j]) d[i][j] = d[i][k]+d[k][j]; if (n == 3) { printf("%d\n", (d[1][2]+d[2][3])*2); return 0; } n1 = (n-2)/2; n2 = n-2-n1; //求从家、花店开始,走到点i,经过的点为j的最短路 //q=0:从家开始,q=1:从花店开始 for (q=0; q<=1; ++q) { //初始化状态 for (i=1; i<=n; ++i) for (j=0; j<e[n-2]; ++j) f[q][i][j] = inf; if (q == 0) { for (i=2; i<n; ++i) f[q][i][e[i-2]] = d[1][i]; } else { for (i=2; i<n; ++i) f[q][i][e[i-2]] = d[n][i]; } //dp for (j=1; j<e[n-2]; ++j) if (cnt[j] < n2) for (i=2; i<n; ++i) if (f[q][i][j] < inf) for (k=2; k<n; ++k) if (f[q][i][j]+d[i][k] < f[q][k][j|e[k-2]]) f[q][k][j|e[k-2]] = f[q][i][j]+d[i][k]; } ans = inf; //枚举先走到的一半为sta for (sta=0; sta<e[n-2]; ++sta) if (cnt[sta] == n1) { //前半段 x = inf; //x记录前半段的最短距离 //枚举前一半中最后一个收割的点是i for (i=2; i<n; ++i) if (sta&e[i-2]) //枚举后一半中第一个收割的点是j for (j=2; j<n; ++j) if (!(sta&e[j-2])) if (f[0][i][sta]+d[i][j]+f[1][j][e[n-2]-1-sta] < x) x = f[0][i][sta]+d[i][j]+f[1][j][e[n-2]-1-sta]; //后半段 //枚举前一半中最后一个播种的点是i for (i=2; i<n; ++i) if (sta&e[i-2]) //枚举后一半中第一个播种的点是j for (j=2; j<n; ++j) if (!(sta&e[j-2])) if (x+f[1][i][sta]+d[i][j]+f[0][j][e[n-2]-1-sta] < ans) ans = x+f[1][i][sta]+d[i][j]+f[0][j][e[n-2]-1-sta]; } printf("%d\n", ans); return 0; }
折花枝,恨花枝,准拟花开人共卮,开时人去时。
怕相思,已相思,轮到相思没处辞,眉间露一丝。