zoukankan      html  css  js  c++  java
  • 11.3 校内模拟赛解题报告

    T1

    算出 (x, y) 分别是 (2) 的几次方也就是在多少层,让 (x, y) 跳到同一层,当 (x, y) 不相等是就向上跳,记录跳的次数。

    T2

    概率期望 DP。
    首先要发现一个性质,每个位置的颜色于这个位置修改了多少次有关,而与中间的过程没有关系。
    考虑每个位置被选中了多少次?
    假设一次作画,选择的区间为 ([l, r]), 区间的长度为 (len = r - l + 1), 考虑一个位置被选中其他的位置随便选的方案数,它会被选中 (2 ^ {len - 1})次, 子集的情况是 (2 ^ {len}),每个位置被选中的概率为 (frac 12)

    (f[k][i][j]) 表示操作了 (k) 次,第 (i) 张画纸改成颜色 (j) 的概率。不改转移到 (f[k+1][i][j]),改转移到 (f[k+1][i][j imes h \% c]。)
    最后的答案=(sum f[b[i]][i][j] imes j)(b[i]) 表示 (i) 位置被操作了多少次。
    时间复杂度 (O(n ^ 4))

    /*
    Date:
    Source:
    Knowledge:
    */
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define orz cout << "AK IOI" << "
    "
    #define int long long 
    
    using namespace std;
    const int maxn = 110;
    
    int read()
    {
    	int x = 0, f = 1; char ch = getchar();
    	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
    	while(ch <= '9' && ch >= '0') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
    	return x * f;
    }
    void print(int X)
    {
    	if(X < 0) X = ~(X - 1), putchar('-');
    	if(X > 9) print(X / 10);
    	putchar(X % 10 ^ '0');
    }
    int Max(int a, int b){
    	return a > b ? a : b;
    }
    int Min(int a, int b){
    	return a < b ? a : b;
    }
    int n, c, k, b[maxn];
    double ans, f[maxn][maxn][maxn];
    signed main()
    {
    	//freopen("paint.in", "r", stdin);
    	//freopen("paint.out", "w", stdout);
    	n = read(), c = read(), k = read();
    	for(int i = 1; i <= k; i++)
    	{
    		int l = read(), r = read();
    		b[l]++, b[r + 1]--;
    	}
    	for(int i = 1; i <= n; i++) b[i] += b[i - 1];
    	for(int i = 1; i <= n; i++) f[0][i][1] = 1;
    	for(int i = 1; i <= n; i++) //第 i 张 
    	{
    		for(int j = 0; j < b[i]; j++) // 改动了多少次 
    		{
    			for(int k = 0; k < c; k++)  // 改成什么颜色  
    			{
    				f[j + 1][i][k] += f[j][i][k] / 2; // 不改 
    				for(int l = 0; l < c; l++) //改 
    				f[j + 1][i][(k * l) % c] += f[j][i][k] / c / 2;  
    			}
    		} 
    	} 
    	for(int i = 1; i <= n; i++) 
    		for(int j = 0; j < c; j++) 
    			ans += f[b[i]][i][j] * j;
    	printf("%.3lf", ans);
    	//fclose(stdin);
    	//fclose(stdout);
    	return 0;
    }
    

    优化:
    相同颜色的纸改的结果的概率相同,而且开始都是1。
    所以 (i) 那一维可以压去,即 (f[k][j]) 表示一张纸操作了 (k) 次,变成颜色 (j) 的概率。
    时间复杂度 (O(n ^3))

    /*
    Date:
    Source:
    Knowledge:
    */
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define orz cout << "AK IOI" << "
    "
    #define int long long 
    
    using namespace std;
    const int maxn = 110;
    
    int read()
    {
    	int x = 0, f = 1; char ch = getchar();
    	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
    	while(ch <= '9' && ch >= '0') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
    	return x * f;
    }
    void print(int X)
    {
    	if(X < 0) X = ~(X - 1), putchar('-');
    	if(X > 9) print(X / 10);
    	putchar(X % 10 ^ '0');
    }
    int Max(int a, int b){
    	return a > b ? a : b;
    }
    int Min(int a, int b){
    	return a < b ? a : b;
    }
    int n, c, k, b[maxn];
    double ans, f[maxn][maxn];
    signed main()
    {
    	//freopen("paint.in", "r", stdin);
    	//freopen("paint.out", "w", stdout);
    	n = read(), c = read(), k = read();
    	for(int i = 1; i <= k; i++)
    	{
    		int l = read(), r = read();
    		b[l]++, b[r + 1]--;
    	}
    	for(int i = 1; i <= n; i++) b[i] += b[i - 1];
    	f[0][1] = 1;
    	for(int j = 0; j < k ; j++) // 改动了多少次 
    	{
    		for(int k = 0; k < c; k++)  // 改成什么颜色  
    		{
    			f[j + 1][k] += f[j][k] / 2; // 不改 
    			for(int l = 0; l < c; l++) //改 
    			f[j + 1][(k * l) % c] += f[j][k] / c / 2;  
    		}
    	} 
    	for(int i = 1; i <= n; i++) 
    		for(int j = 0; j < c; j++) ans += f[b[i]][j] * j;
    	printf("%.3lf", ans);
    	//fclose(stdin);
    	//fclose(stdout);
    	return 0;
    }
    
    

    T3

    30 pts

    100

    看到数据范围都很小,可以想到状压,又因为题目中要求的是最短距离,所以就想到状压最短路。

    (f[i][S]) 表示从家到点 (i),经过了状态为 (S) 的点集。

    (g[i][S]) 表示从花店到点 (i),经过了状态为 (j) 的点集。

    Floyd 预处理任意两点间的最短距离 dis。
    上面这个 (f), (g) 数组可以预处理出来。只需要枚举 (S)(1) 的个数 (leq frac {n - 2}2 + 2)的状态即可。复杂度就被优化掉一个 n。

    然后考虑首先选择哪 (frac {n - 2}2) 个花田收割,设枚举的收割的花田的状态为 S。

    我们考虑收割的过程,把前一半的最短路和后一半的最短路合并起来。
    直接进行搜索。
    收割过程,$ res1 = min(res1, f[S | 1][x] + g[M ^ (S | 1)][y] + dis[x][y])(。 播种过程,)res2 = min(res2, g[S | (1 << n - 1)][x] + f[M ^ (S | (1 << n - 1))][y] + dis[x][y])$。

    /*
    Date:
    Source:
    Knowledge:
    */
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define orz cout << "AK IOI" << "
    "
    
    using namespace std;
    const int maxn = 2e6 + 10;
    
    int read()
    {
    	int x = 0, f = 1; char ch = getchar();
    	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
    	while(ch <= '9' && ch >= '0') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
    	return x * f;
    }
    void print(int X)
    {
    	if(X < 0) X = ~(X - 1), putchar('-');
    	if(X > 9) print(X / 10);
    	putchar(X % 10 ^ '0');
    }
    int Max(int a, int b){
    	return a > b ? a : b;
    }
    int Min(int a, int b){
    	return a < b ? a : b;
    }
    
    int n, m, N, M, ans = 0x3f3f3f3f;
    int dis[22][22], f[maxn][22], g[maxn][22];
    int a[22], sc = 0;
    int b[22], top = 0;
    
    
    void dfs(int S, int pos, int cnt) 
    {
        if(cnt > N) return ;
        if(pos == n) 
    	{
            if(cnt != N) return ;
            int res1 = 0x3f3f3f3f, res2 = 0x3f3f3f3f;
            for(int i = 1; i <= sc; i++) 
    		{
                for(int j = 1; j <= top; j++) 
    			{
                    int x = a[i], y = b[j];
                    res1 = min(res1, f[S | 1][x] + g[M ^ (S | 1)][y] + dis[x][y]);
                    res2 = min(res2, g[S | (1 << n - 1)][x] + f[M ^ (S | (1 << n - 1))][y] + dis[x][y]);
                }
            }
            ans = min(ans, res1 + res2);
            return ;
        }
        a[++sc] = pos;
        dfs(S | (1 << pos - 1), pos + 1, cnt + 1);
        --sc;
        b[++top] = pos;
        dfs(S, pos + 1, cnt);
        --top;
    }
    
    signed main()
    {
    	n = read(), m = read();
    	N = (n - 2) / 2, M = (1 << n) - 1;
    	memset(dis, 0x3f, sizeof dis);
    	for(int i = 1; i <= n; i++) dis[i][i] = 0;
    	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);
        }
        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]);
        if(n == 3) 
    	{
            printf("%lld
    ", 1ll * (dis[1][2] + dis[2][3]) * 2);
            return 0; 
        }
        memset(f, 63, sizeof f);
        f[1][1] = 0;
        for(int S = 0; S < (1 << n); S++) 
    	{
            int cnt = 0;
            for(int i = 1; i <= n; i++) if(S & (1 << i - 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[S | (1 << j - 1)][j] = min(f[S | (1 << j - 1)][j], f[S][i] + dis[i][j]);
                }
            }
        }
        memset(g, 63, sizeof g);
        g[(1 << n - 1)][n] = 0;
        for(int S = 0; S < (1 << n); S++) 
    	{
            int cnt = 0;
            for(int i = 1; i <= n; i++) if(S & (1 << i - 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[S | (1 << j - 1)][j] = min(g[S | (1 << j - 1)][j], g[S][i] + dis[i][j]);
                }
            }
        }
        dfs(0, 2, 0);
        printf("%d", ans);
        return 0;
    }
    
    
  • 相关阅读:
    VS2008 环境中完美搭建 Qt 4.7.4 静态编译的调试与发布 Inchroy's Blog 博客频道 CSDN.NET
    编写可丢弃的代码
    c++ using namespace std; 海明威 博客园
    解决MySQL server has gone away
    nginx upstream 调度策略
    (2006, 'MySQL server has gone away') 错误解决 dba007的空间 51CTO技术博客
    Linux IO模型漫谈(2) 轩脉刃 博客园
    redis源码笔记 initServer 刘浩de技术博客 博客园
    MySQLdb批量插入数据
    词库的扩充百度百科的抓取你知道这些热词吗? rabbit9898 ITeye技术网站
  • 原文地址:https://www.cnblogs.com/yangchengcheng/p/15506536.html
Copyright © 2011-2022 走看看