zoukankan      html  css  js  c++  java
  • 11.3 校内模拟赛

    总结:

    祭考试做出一道期望 dp /se

    考试心路历程:

    5 min 读完 T1, ahhhhhh,签到题,10 min 写完,一发过大样例。

    8:20 开干 T2,期望 dp,读完题,感觉可做。

    写了好久,调过样例,写了对拍,一拍就挂,rnm。

    调半天,转移写挂 = =

    10:10 开 T3

    T3 题目好奇怪,为啥开头是 T2 的题目啊,没用,没用,删了。

    艹,这花店在哪儿,我家在哪儿,我咋找不到我家!!

    读了好几遍,没读懂题,麻了,睡觉。

    赛后:为啥我 T3 题目少了一个自然段啊 !!!!

    T1 三向城

    题面

    solution

    手摸题目,你发现这是个满二叉树。

    然后你会发现,他的层数其实很少。

    你还会发现每个节点的父亲就是改节点 / 2

    然后你就暴力向上跳就好了 = =

    code

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    const int MAX = 35;
    int read() {
      int x = 0, f = 1; char c = getchar();
      while(c < '0' || c > '9') {if(c == '-') f = -1;c = getchar();}
      while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = getchar();}
      return x * f;
    }
    int q, Ans;
    int get(int x) {
      for (int i = 1; i <= MAX; i++) 
      	if((1 << i) > x) return i;	 
    }
    signed main(){
      //freopen("city.in", "r", stdin);
      //freopen("city.out", "w", stdout);
      q = read();
      for (int i = 1, x, y; i <= q; i++) {
         x = read(), y = read();
         Ans = 0;
    	 int dep_x = get(x), dep_y = get(y);
    	 if(dep_x < dep_y) swap(x, y), swap(dep_x, dep_y);
    	 while(dep_x != dep_y) {
    	   x = x / 2;
    	   Ans++, dep_x--;
    	 } 	
    	 while(x != y) {
    	   x = x / 2, y = y / 2;
    	   Ans += 2;
    	 }
    	 cout<<Ans<<"
    ";
      }
      return 0;
    }
    
    

    T2 灵魂画师

    题面

    solution

    期望 = 概率 * 权值

    显然权值就是颜色,考虑怎么计算每个位置变成某个颜色的概率。

    不难发现,某个位置变成哪个颜色只与它被选中的次数有关。

    (P_{i, j}) 表示 (i) 一个点出现在 (i) 个区间内,被选中 (j) 次的概率。

    显然 (P_{i, j} = frac{C_{i}^{j}}{2})

    (f_{i, j}) 表示选中 (i) 次,变为颜色 (j) 的概率。

    (f_{i + 1, j imes o \% c} += f_{i, j} / c)

    (P)(f) 都可以预处理出来。

    (Ans = sum_{i = 1}^{i leq n}sum_{j = 0}^{cnt[i]}sum_{o = 0}^{o < c} f_{j, o} imes P_{cnt[i], j} imes o)

    code

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN = 110;
    const double eps = 1e-7;
    int read() {
      int x = 0, f = 1; char c = getchar();
      while(c < '0' || c > '9') {if(c == '-') f = -1;c = getchar();}
      while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = getchar();}
      return x * f;
    }
    int n, c, k, cnt[MAXN];
    double C[MAXN][MAXN], P[MAXN][MAXN], Ans;
    void Init_C() {
      C[0][0] = 1;
      for (int i = 1; i <= 100; i++) {
      	C[i][0] = 1;
      	C[i][0] = C[i][0] / 2.0;
      	for (int j = 0; j <= i; j++) {
    	   C[i][j] = C[i - 1][j - 1] / 2.0 + C[i - 1][j] / 2.0;
        }
      }
    }
    void Init_P() {
      P[0][1] = 1;
      for (int i = 0; i <= k; i++) 
        for (int j = 0; j < c; j++) {
          if(P[i][j] <= eps) continue;
    	  for (int o = 0; o < c; o++) {
    	     P[i + 1][j * o % c] = (P[i + 1][j * o % c] + P[i][j] / c);
    	   }	
        }
    }
    int main(){
      n = read(), c = read(), k = read();
      Init_C(), Init_P();
      for (int i = 1; i <= k; i++) {
        int x = read(), y = read();
        for (int j = x; j <= y; j++) cnt[j]++;
      } 
      for (int i = 1; i <= n; i++) 
      	for (int j = 0; j <= cnt[i]; j++) 
      	  for (int o = 0; o < c; o++) Ans += C[cnt[i]][j] * P[j][o] * o;
      printf("%.3lf
    ", Ans);
      return 0;
    }
    

    T3 香子兰

    题面

    solution

    直接搬 szt 的了 /cy

    你看这个数据范围就知道要状压,你看它要求最短路径就得状压最短路。

    我们先跑个 (Folyd) 求出两两之间的最短距离。

    我们在设两个数组 (f[S][i],g[S][i]) 分别表示以 (1) 作为出发点,已经进行收割/播种的状态为 (S),最后一个点为 (i) 的最短距离,(g) 数组则表示以 (n) 为出发点。

    上面这个 (f,g) 数组可以预处理出来。时间复杂度为 (O(2^nn^2)),这个复杂度有点危,我们发现我们不用枚举全部的,我们只需要枚举 (S)(1) 的个数 (≤frac{n−2}{2}+2) 的状态即可。复杂度就被我们优化掉一个 (n)(我们本质还是枚举所有子集,只不过在某些子集只做了 (O(n)) Check )

    然后你枚举首先选择哪 (n−2) 个花田收割,设枚举的收割的花田的状态为 (S)

    我们考虑收割的过程,考虑怎么把前一半的最短路和后一半的最短路合并起来,那就是,枚举在集合中的点 (i) 和不在集合中的点 (j),设答案为 (res),则:

    (res=min{f[S|1][i] + g[M oplus (S|(1<<n−1))][j]+dis[i][j]})
    其中 (M) 表示所有点的全集。

    这样就保证了 (S) 状态中选中的点一定会在前 (frac{n−2}{2}) 花田里收割,剩余的点在后来收割。

    同理,我们考虑播种的过程,其实就是反过来,我们再设一个播种的答案 (ans),则

    (ans=min{g[S|1][i]+f[M oplus (S|(1<<n−1))][j]+dis[i][j]})

    最终答案就是 (min{res+ans})

    这个直接上搜索就行,控制一下搜索上限,可以控制复杂度为 (O(2^{frac{n−2}{2}}frac{n−2}{2}^2))

    code

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN = 21;
    const int INF = 0x3f3f3f3f3f;
    int read() {
      int x = 0, f = 1; char c = getchar();
      while(c < '0' || c > '9') {if(c == '-') f = -1;c = getchar();}
      while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = getchar();}
      return x * f;
    }
    int n, m, dis[MAXN][MAXN], N, M, Ans = 0x3f3f3f3f;
    int f[MAXN][(1 << 20) - 1], g[MAXN][(1 << 20) - 1];
    void Init_dis() {
      for (int i = 1; i <= n; i++) dis[i][i] = 0;
      for (int k = 1; k <= n; k++) 
        for (int i = 1; i <= n; i++) 
          for (int j = 1; j <= n; j++) 
            dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
    }
    void Init_F() {
      memset(f, 0x3f, sizeof f);
      f[1][1] = 0;
      for (int s = 0; s < (1 << n); s++) {
      	int cnt = 0;
      	for (int k = 1; k <= n; k++) if(s & (1 << k - 1)) cnt++;
    	if (cnt > N + 2) continue; 
        for (int i = 1; i <= n; i++) {
          if(!(s & (1 << i - 1))) continue;
    	  for (int j = 1; j <= n; j++) {
    	  	if(s & (1 << j - 1)) continue;
    	    f[j][s | (1 << j - 1)] = min(f[j][s | (1 << j - 1)], f[i][s] + dis[i][j]);
    	  }
    	}
      }
    }
    void Init_G() {
      memset(g, 0x3f, sizeof g);
      g[n][1 << n - 1] = 0;
      for (int s = 0; s < (1 << n); s++) {
      	int cnt = 0;
      	for (int k = 1; k <= n; k++) if(s & (1 << k - 1)) cnt++;
      	if(cnt > N + 2) continue;
      	for (int i = 1; i <= n; i++) { 
      	  if(!(s & (1 << i - 1))) continue;
      	  for (int j = 1; j <= n; j++) {
      	    if(s & (1 << j - 1)) continue;
    		g[j][s | (1 << j - 1)] = min(g[j][s | (1 << j - 1)], g[i][s] + dis[i][j]);	 
    	  }
    	}
      } 
    }
    int In[MAXN], Out[MAXN], Incnt, Outcnt;
    void dfs(int s, int pos, int cnt) {
       if(cnt > N) return ;
       if(pos == n) {
         if(cnt != N) return ;
         int ret_1 = INF, ret_2 = INF;
         for (int i = 1; i <= Incnt; i++) {
           for (int j = 1; j <= Outcnt; j++) {
           	 int x = In[i], y = Out[j];
           	 ret_1 = min(ret_1, f[x][s | 1] + g[y][(s | 1) ^ M] + dis[x][y]);
           	 ret_2 = min(ret_2, g[x][s | (1 << n - 1)] + f[y][(s | (1 << n - 1)) ^ M] + dis[x][y]);
    	   }
    	 }
    	 Ans = min(Ans, ret_1 + ret_2);
         return ;	 
       }
       In[++Incnt] = pos;
       dfs(s | (1 << pos - 1), pos + 1, cnt + 1);
       Incnt--;
       Out[++Outcnt] = pos;
       dfs(s, pos + 1, cnt);
       Outcnt--;
    }
    int main(){
      n = read(), m = read();
      N = (n - 2) / 2, M = (1 << n) - 1;
      memset(dis, 0x3f, sizeof dis);
      for (int i = 1, u, v, w; i <= m; i++) {
      	 u = read() + 1, v = read() + 1, w = read();
      	 dis[u][v] = dis[v][u] = min(dis[u][v], w);
      }
      Init_dis();
      if(n == 3) {
      	 cout<<(dis[1][2] + dis[2][3]) * 2;
      	 return 0;
      }
      Init_F(), Init_G();
      dfs(0, 2, 0);
      cout<<Ans;
      return 0;
    }
    
  • 相关阅读:
    C++内存泄漏检测拾遗
    利用ACE_Get_Opt解析命令
    ACE Reactor模型学习
    Acceptor模型和Connector模型学习
    IOCP模型示例
    ACE Proactor模型示例
    如何:为 ASP.NET 网页全球化设置区域性和 UI 区域性
    Update Calendar Item In excaheng server by exchange web services
    ASP.NET Security Architecture
    Error message when you visit a Web site that is hosted on IIS 7.0: "HTTP Error 500.19 – Internal Server Error"
  • 原文地址:https://www.cnblogs.com/Arielzz/p/15504838.html
Copyright © 2011-2022 走看看