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\{ \begin{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} \right. \]

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

\[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 
#include 
#include 
#include 
#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\n", 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 << '\n'; 
    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
#define lson (o<<1)
#define rson (o<<1|1)
#define fi first
#define sc second
#define dbg(x) cout<<#x<<" = "<<(x)<'9');
    do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
    return f*x;
}
template inline T max(T x,T y,T z){return max(max(x,y),z);}
template inline T min(T x,T y,T z){return min(min(x,y),z);}
template inline T sqr(T x){return x*x;}
template inline void checkmax(T &x,T y){x=max(x,y);}
template inline void checkmin(T &x,T y){x=min(x,y);}
template 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 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

T2

暴力

//By:Loceaner
#include 
#include 
#include 
#include 
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 
#include 
#include 
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 
#include 
#include 
#include 

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\n", ans/2);
        else printf("%d\n", ans/2);
    }
}

你可能感兴趣的:(2019.10.13考试解题报告)