• 2019.10.13考试解题报告


    2019.10.13考试解题报告

    总结

    期望得分:(100 + 30 + 0)
    实际得分:(100 + 50 + 0)

    神奇的多得了(20)分?
    花两个多小时去推(T1)的式子,结果是推出来了,慌慌张张差点翻车
    去打(T2)的暴力,顺便打了几个(if),然后就(30-->50)?心里有点小激动
    (T3)没时间做了……我菜


    思路

    T1

    一开始就想写正解,发现不会,于是打了个(40)分的暴力保底,对暴力的式子进行拆解和优化,得到了下面的过程

    要求的是

    [min sum_{j = 1}^{n} abs(a_i - a_j) * b_j ]

    首先去掉绝对值号,发现我们能把这个式子分成两部分

    [ ans +=left{ egin{aligned} sum_{j = 1}^{i}(a_i - a_j) * b_j (a_i > a_j) \ sum_{j = i}^{n}(a_j - a_i) * b_j (a_i < a_j) end{aligned} ight. ]

    然后拆解发现,前一部分变成了

    [a_ib_1 - a_1b_1 + a_ib_2 - a_2b_2 + ……a_ib_j-a_jb_j ]

    后一部分变成了

    [a_jb_j-a_ib_j+a_{j+1}b_{j+1} -a_ib_{j+1}+……a_nb_n-a_ib_n ]

    然后在合并一下子(我懒得写了)

    然后发现我们可以用前缀和!!!

    然后就做出来了!!

    T2

    (30)分暴力很好打,暴搜就行了

    (60)的话,分别枚举两个骰子点数,计算出来每种点数和的方案数(除以(6^n)得到概率)
    如果你扔出了(i)点,那你胜利的方案是对手扔出([1,i)),从小到大枚举你的点数,同时
    计算对手的前缀和

    满分做法
    计算每种点数的概率
    计算(i)个骰子的概率时,考虑最后一个骰子的点数为(1-6)的每种情况,可以从(i-1)个骰
    子概率转移过来。
    (f[i][j])表示(i)个骰子扔出(j)的概率
    (f[i][j] = sum{f[i-1][j-k]/6}(1≤k≤6))
    递推即可,复杂度(O(n²))

    T3

    神仙题神仙题神仙题


    代码

    T1

    考场满分

    //By:Loceaner
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define int long long
    using namespace std;
    
    inline int read() {
    	char c = getchar();
    	int x = 0, f = 1;
    	for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for( ; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + (c ^ 48);
    	return x * f;
    }
    
    const int N = 1e6 + 11;
    
    struct node {
    	int a, b, id, c;
    } e[N];
     
    bool cmp(node x, node y) {
    	return x.a < y.a;
    }
    
    int n, sum2[N], sum3[N], ans = 0x3f3f3f3f3f3f3f3f;
    bool flag = 1;
    
    signed main() {
    	n = read();
    	for(int i = 1; i <= n; i++) {
    		e[i].a = read();
    		if(i != 1)
    			if(e[i].a != e[i - 1].a) 
    				flag = 0;
    	}
    	for(int i = 1; i <= n; i++) e[i].b = read(), e[i].c = e[i].a * e[i].b;
    	if(flag) return cout << "0
    ", 0;
    	stable_sort(e + 1, e + 1 + n, cmp);
    	for(int i = 1; i <= n; i++) {
    		sum2[i] = sum2[i - 1] + e[i].b;
    		sum3[i] = sum3[i - 1] + e[i].c;
    	}
    //	for(int i = 1; i <= n; i++) {
    //		int now = 0;
    //		for(int j = 1; j <= n; j++) {
    //			now += abs(e[i].a - e[j].a) * e[j].b;
    //		}
    //		ans = min(ans, now);
    //	}
    	int now = 0;
    	for(int i = 1; i <= n; i++) {
    		now = e[i].a * sum2[i - 1] - sum3[i - 1] + (sum3[n] - sum3[i]) - e[i].a * (sum2[n] - sum2[i]);
    		ans = min(ans, now);
    	}
    	cout << ans << '
    '; 
    	return 0;
    }
    /*
    6
    2 1 3 3 2 4
    5 1 1 2 2 2
    10
    1 2 2 5 6 6 8 10 10 10
    9 55 41 2 4 6 3 2 4 10
    */
    

    题解里的正解

    #include<bits/stdc++.h>
    #define lson (o<<1)
    #define rson (o<<1|1)
    #define fi first
    #define sc second
    #define dbg(x) cout<<#x<<" = "<<(x)<<endl;
    typedef long long ll;
    typedef unsigned int uint;
    typedef unsigned long long ull;
    using namespace std;
    const double pi=acos(-1);
    const double eps=1e-6;
    inline int lowbit(int x){return x&(-x);}
    inline int read(){
        int f=1,x=0;char ch;
        do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
        do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
        return f*x;
    }
    template<typename T> inline T max(T x,T y,T z){return max(max(x,y),z);}
    template<typename T> inline T min(T x,T y,T z){return min(min(x,y),z);}
    template<typename T> inline T sqr(T x){return x*x;}
    template<typename T> inline void checkmax(T &x,T y){x=max(x,y);}
    template<typename T> inline void checkmin(T &x,T y){x=min(x,y);}
    template<typename T> inline void read(T &x){
    x=0;T f=1;char ch;do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
    do x=x*10+ch-'0',ch=getchar();while(ch<='9'&&ch>='0');x*=f;
    }
    template<typename A,typename B,typename C> inline A fpow(A x,B p,C yql){
        A ans=1;
        for(;p;p>>=1,x=1LL*x*x%yql)if(p&1)ans=1LL*x*ans%yql;
        return ans; 
    }
    struct FastIO{
        static const int S=1310720;
        int wpos;char wbuf[S];
        FastIO():wpos(0) {}
        inline int xchar(){
            static char buf[S];
            static int len=0,pos=0;
            if(pos==len)pos=0,len=fread(buf,1,S,stdin);
            if(pos==len)return -1;
            return buf[pos++];
        }
        inline int read(){
            int c=xchar(),x=0;
            while(c<=32&&~c)c=xchar();
            if(c==-1)return -1;
            for(;'0'<=c&&c<='9';c=xchar())x=x*10+c-'0';
            return x;
        }
    }io;
    //#define read io.read
    const int N=1e6+10;
    const int yql=1e9+7;
    struct Node{
        int x,v;
    }a[N];
    inline bool cmp(Node a,Node b){return a.x<b.x;}
    int n,m;
    ll cur=0,ans=0,k1,k2; 
    int main(){
        freopen("shiroha1.in","r",stdin);
        freopen("shiroha1.out","w",stdout);
        n=read();
        for(int i=1;i<=n;i++)a[i].x=read();
        for(int i=1;i<=n;i++)a[i].v=read();
        sort(a+1,a+n+1,cmp);
        for(int i=1;i<=n;i++)cur=cur+1LL*(a[i].x-a[1].x)*a[i].v;
        ans=cur;
        for(int i=2;i<=n;i++)k1+=a[i].v;k2=a[1].v;
        for(int i=2;i<=n;i++){
            //dbg(cur);
            //cur=(cur-1LL*k1*(a[i].x-a[i-1].x)%yql+yql)%yql;
            //cur=(cur+1LL*k2*(a[i].x-a[i-1].x)%yql)%yql;
            cur=cur-1LL*k1*(a[i].x-a[i-1].x);
            cur=cur+1LL*k2*(a[i].x-a[i-1].x);
            k1-=a[i].v;k2+=a[i].v;
            checkmin(ans,cur);
        }
        printf("%lld
    ",ans);
    }
    

    T2

    暴力

    //By:Loceaner
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    inline int read() {
    	char c = getchar();
    	int x = 0, f = 1;
    	for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for( ; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + (c ^ 48);
    	return x * f;
    }
    
    int x, y, nowx, nowy, cnta, cntb, cntp;
    
    void dfs2(int tot, int ans) {
    	if(tot == y) {
    		nowy = ans;
    		if(nowx == nowy) cntp++;
    		else if(nowx > nowy) cnta++;
    		else cntb++;
    		return;
    	}
    	for(int i = 1; i <= 6; i++) {
    		dfs2(tot + 1, ans + i);
    	}
    }
    
    void dfs1(int tot, int ans) {
    	if(tot == x) {
    		nowx = ans;
    		dfs2(0, 0);
    		return;
    	}
    	for(int i = 1; i <= 6; i++) {
    		dfs1(tot + 1, ans + i);
    	}
    }
    
    int main() {
    	x = read(), y = read();
    	if(x + y <= 10) {
    		dfs1(0, 0);
    		printf("%.2lf%%", ((1.0 * cnta) / (cnta + cntb + cntp)) * 100);
    	} 
    	else if(x - 7 >= y) cout << "100.00%";
    	else if(y - 7 >= x) cout << "0.00%";
    	else if(x > y * 6) cout << "100.00%";
    	else if(x == y) cout << "50%";
    	else cout << "0.00%";
    	return 0;
    }
    
    

    正解

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    
    double a[1001][7001], sx, sy, ans;
    int x, y;
    
    int main() {
    	scanf("%d%d", &x, &y);
    	int xy = x > y ? x : y;
    	for(int i = 1; i <= 6; i++) a[1][i] = 1;
    	for(int i = 2; i <= xy; i++)
    		for(int j = i; j <= 6 * i; j++)
    			for(int k = 1; k <= 6; k++)
    				if(j > k) a[i][j] += a[i - 1][j - k] / 6.0;
    	for(int i = x; i <= 6 * x; i++) {
    		for(int j = y; j <= 6 * y; j++) 
    			sy += a[x][i] * a[y][j];
    		if(i <= y) continue;
    		for(int j = y; j <= i - 1; j++) 
    			sx += a[y][j] * a[x][i];
    	}
    	ans = sx / sy * 100;
    	printf("%.2lf%%", ans);
    	return 0;
    }
    

    T3

    正解

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    
    using namespace std;
    
    const int MAXN = 1000010;
    const int MAXL = 22;
    
    int rmin[MAXL][MAXN], rmax[MAXL][MAXN];
    
    int n, q;
    int a[MAXN];
    
    inline void init_rmq() {
        for (int i = 1; i < MAXL; i++)  {
            for (int j = 0; j + (1 << i) <= n; j++) {
                rmin[i][j] = min(rmin[i-1][j], rmin[i-1][j+(1<<(i-1))]);
                rmax[i][j] = max(rmax[i-1][j], rmax[i-1][j+(1<<(i-1))]);
            }
        }
    }
    
    inline bool test(int d, int m) {
        int l = 0, i;
        for (i = 0; i < m && l < n; i++) {
            int r = l, smin = 1000000001, smax=0;
            for (int j = MAXL - 1; j >= 0; j--) {
                if (r + (1 << j) <= n) {
                    int tmin = rmin[j][r], tmax = rmax[j][r];
                    if (max(smax, tmax) - min(smin, tmin) <= d) {
                        smax = max(smax, tmax);
                        smin = min(smin, tmin);
                        r += (1 << j);
                    }
                }
            }
            l = r;
        }
        return l == n;
    }
    
    inline int work(int m) {
        int l = 0, r = 1000000001;
        while (l < r) {
            int mid = (l + r) >> 1;
            if (test(mid, m)) {
                r = mid;
            } else {
                l = mid + 1;
            }
        }
        return l;
    }
    
    int main() {
        scanf("%d", &n);
        for (int i = 0; i < n; i++) {
            scanf("%*d%d", &rmin[0][i]);
            rmax[0][i] = rmin[0][i];
        }
        init_rmq();
        scanf("%d", &q);
        for (int i = 0; i < q; i++) {
            int m;
            scanf("%d", &m);
            int ans = work(m);
            if (ans % 2) printf("%d.5
    ", ans/2);
            else printf("%d
    ", ans/2);
        }
    }
    
  • 相关阅读:
    二分查找 【数组的二分查找】
    二分答案 [TJOI2007]路标设置
    队测 逆序对 permut
    【线段树】 求和
    状压DP Sgu223 骑士
    状压DP Poj3311 Hie with the Pie
    状压DP入门 传球游戏之最小总代价
    状压DP 小W选书籍
    状压DP [Usaco2008 Nov]mixup2 混乱的奶牛
    __gcd()用法
  • 原文地址:https://www.cnblogs.com/loceaner/p/11668171.html
Copyright © 2020-2023  润新知