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;
    }
    
    
  • 相关阅读:
    jvm启动参数调优
    程序员之在plmm面前清新脱俗的装逼
    .gradle文件配置
    fan greatwall
    归档
    关于
    Navicat Premium 15 永久激活版安装教程
    Python+unittest+requests 接口自动化测试框架搭建 完整的框架搭建过程 实战
    通过pycharm使用git和github的步骤(图文详解)
    Ubuntu-18.04.1-live-server-amd64.iso安装全过程
  • 原文地址:https://www.cnblogs.com/yangchengcheng/p/15506536.html
Copyright © 2011-2022 走看看