2021 icpc网络赛

A:就是个简单的模拟题,复杂度\(n^2\),注意就是如果用pair排序wa了的话可以试试这个样例
\(3 2 1 2 1\)

G:求极限
可以直接泰勒展开到 t 阶,或者洛必达写
泰勒公式:

\[f(x) = \frac {f(x_0)} {0!} + \frac {\dot{f(x_0)}(x - x_0)} {1!} + \frac {\ddot{f(x_0)}{(x - x_0)}^2} {2!} + ..... = \sum_{i=0}^n \frac {{f^n(x_0)}{(x - x_0)}^i} {i!} \]

手推一下就知道\(x -> 0,ln(1 + x) = 0 + x - \frac {x^2} 2 + \frac {x^3} 3....\),把 \(x\)\(bx\)带入,前面乘系数 \(a\),累加即可,那么如果 \(t\) 阶前面的项系数不为0,就是无穷,否则就是t阶的值也就是\(\sum \frac {ab^4} t\)
洛必达也差不多,总共洛t次,如果前面出现分子变成常数了,就不能洛了,答案就是无穷。只有上面下面都是0才能一直洛下去,答案就是最后的项除 \(t!\)

void run() {
    int n, t; cin >> n >> t;
    for(int i = 1; i <= n; ++ i) {
        cin >> a[i] >> b[i];
        f[1] += a[i] * b[i];
        f[2] += -a[i] * b[i] * b[i];
        f[3] += a[i] * b[i] * b[i] * b[i];
        f[4] += -a[i] * b[i] * b[i] * b[i] * b[i];
        f[5] += a[i] * b[i] * b[i] * b[i] * b[i] * b[i];
    }
    if(t == 0)  cout << "0";
    else {
        for(int i = 1; i < t; ++ i)
            if(f[i] != 0) {
                cout << "infinity";
                return ;
            }
        int fm = 1;
        if(f[t] == 0)   cout << "0";
        else if(f[t] % t == 0)  cout << f[t] / t;
        else cout << f[t] << '/' << t;
    }
    return ;
}

K:概率dp
对于每个人拿到某个盘子的概率,显然是上一个状态推过来的,递推式就是$dp[i][j] = \sum_{i & (1 << j)} dp[i - (1 << j)][j] * p_j $,第一维是状态,第二维是拿的第几个盘子,但是这样复杂度是\(2^n * n * n\),是不行的,那么考虑优化就是不开两维,然后用每个状态推到下一个状态的概率,然后用另一个数组存答案。

int a[22][22], ans[22][22];
int sz[1 << 20];
int dp[1 << 20];

void run() {
    int n; cin >> n;
    for(int i = 0; i < n; ++ i)
        for(int j = 0; j < n; ++ j)
            cin >> a[i][j];
    dp[0] = 1;
    int limit = 1 << n; limit --;
    for(int i = 0; i <= limit; ++ i) {
        if(i)   sz[i] = sz[i - (i & -i)] + 1;
        int sum = 0;
        for(int j = 0; j < n; ++ j)
            if(!((1 << j) & i))    sum += a[sz[i]][j];
        int inv = ksm(sum, mod - 2);
        for(int j = 0; j < n; ++ j)
            if(!((1 << j) & i)) {
                dp[i | (1 << j)] = (dp[i | (1 << j)] + dp[i] * a[sz[i]][j] % mod * inv % mod) % mod;
                ans[sz[i]][j] += dp[i] * a[sz[i]][j] % mod * inv % mod;
                if(ans[sz[i]][j] >= mod)    ans[sz[i]][j] -= mod;
            }
    }
    for(int i = 0; i < n; ++ i) {
        for(int j = 0; j < n; ++ j) {
            if(j)   cout << ' ';
            cout << ans[i][j];
        }
        cout << '\n';
    }
    return ;
}

L:线段树区间乘
欧拉函数的结论就是如果\(i, j\)互质,那么\(phi[i * j] = phi[i] * phi[j]\),否则\(phi[i * j] = phi[i] * j\)

posted @ 2021-09-27 19:45  wlhp  阅读(128)  评论(0)    收藏  举报