ABC208


B

题意:有1!, 2!, ..., 10!面值的硬币每个100个,问需要凑成P的最少的硬币数

方法:贪心

#include
#include
#include
#include

using namespace std;

int fac[11];

int main(){
    fac[0] = 1;
    for(int i = 1; i <= 10; i ++) fac[i] = fac[i - 1] * i;
    
    int p;
    cin >> p;
    
    int res = 0;
    for(int i = 10; i >= 1; i --){
        if(p == 0) break;
        int cnt = min(p / fac[i], 100);
        res += cnt;
        p -= cnt * fac[i];
    }
    
    cout << res;
}

C

题意:输入N个人,每个人有一个id,现在有K个糖,如果K比N大,给每个人一个,如果在某一次操作后K小于N,那么给id排名在1~K的所有人一个糖,问第i个人有多少糖(i = 1, 2, ... N)

方法:每个人的基本糖数为k / n, 为每一个人保存序号和id,然后根据id升序排序,然后给前k个人多分一个糖,最后按照序号升序排序,输出答案

#include
#include

using namespace std;

#define int long long

const int N = 2e5 + 10;

struct node{
    int id, pos, val;
}a[N];

int n, k;

int cmp1(const node &n1, const node &n2){
    return n1.id < n2.id;
}

int cmp2(const node &n1, const node &n2){
    return n1.pos < n2.pos;
}

signed main(){
    cin >> n >> k;
    for(int i = 0; i < n; i ++){
        int id;
        cin >> id;
        a[i] = {id, i};
    }
    
    sort(a, a + n, cmp1);
    int p = k % n, q = k / n;
    for(int i = 0; i < n; i ++) a[i].val = q + (i < p);
    sort(a, a + n, cmp2);
    for(int i = 0; i < n; i ++) cout << a[i].val << endl;
}

D

题意:给你一个有向图,问

\[\sum_{i=1}^{n}\sum_{j=1}^{n}\sum_{k=1}^{n}f(i, j, k) \]

其中f(i, j, k)是从i到j只经过结点1~k的最短路径

状态转移:根据i到j的只经过结点1~k的最短路径是否经过k来划分状态,不经过k的最短路为\(f(i, j, k-1)\), 经过k的最短路为\(f(i, k, k - 1) + f(k, j, k - 1)\)

所以\(f(i, j, k) = min(f(i, j, k - 1), f(k, j, k - 1))\)

初始条件:\(f(i, i, 0) = 0, i = 1,...,n\)\(f(a, b, 0) = c\)其中a可以直接到b且权值为c,其他情况\(f(i, j, *) = \inf\)(注意inf要足够大),另外空间可以用滚动数组优化...(开三维数组本地re)

#include
#include
#include
#include

using namespace std;

#define int long long

const int N = 410, INF = 0x3f3f3f3f3f3f3f3f;

int n, m;
int f[N][N][2];

// f[s][t][k] = min(f[s][t][k - 1], f[s][k][k - 1] + f[k][t][k - 1])

// f[s][k][k] f[k][t][k]

// f[s][k][k] = min(f[s][k][k - 1], f[s][k][k - 1] + f[k][k][k - 1])
// f[k][t][k] = min(f[k][t][k - 1], f[k][k][k - 1] + f[k][t][k - 1])


signed main(){
    memset(f, 0x3f, sizeof f);
    
    cin >> n >> m;
    for(int i = 0; i < m; i ++){
        int a, b, c;
        cin >> a >> b >> c;
        f[a][b][0] = c;
    }
    
    for(int i = 1; i <= n; i ++)
        f[i][i][0] = 0;
    
    int res = 0, cur = 1, pre = 0;
    for(int k = 1; k <= n; k ++){
        for(int i = 1; i <= n; i ++)
            for(int j = 1; j <= n; j ++){
                f[i][j][cur] = min(f[i][j][pre], f[i][k][pre] + f[k][j][pre]);
                if(f[i][j][cur] < INF)
                    res += f[i][j][cur];
            }
        cur ^= 1, pre ^= 1;
    }
            
    cout << res;
}