牛客网暑期多校1

B - Symmetric Matrix

思路:将矩阵转换成图的形式,然后推公式。

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define pii pair<int, int>
#define y1 skldjfskldjg
#define y2 skldfjsklejg
 
using namespace std;
 
const int N = 1e5 + 7;
const int M = 1e5 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
 
LL dp[N], sum[N];
int mod, n;
LL fastPow(LL a, LL b) {
    LL ans = 1;
    while(b) {
        if(b & 1) ans = ans * a % mod;
        a = a * a % mod; b >>= 1;
    }
    return ans;
}
 
void init() {
 
    dp[1] = 0;
    dp[2] = 1;
    dp[0] = 1;
    for(int i = 3; i <= n; i++) {
        sum[i] = (i - 1) * sum[i - 1] % mod + (1ll * (i - 1) * (i - 2) / 2) % mod * dp[i - 3] % mod;
        if(sum[i] >= mod) sum[i] -= mod;
 
        dp[i] = (i - 1) * dp[i - 2] % mod + sum[i];
        if(dp[i] >= mod) dp[i] -= mod;
 
    }
}
 
int main() {
    while(scanf("%d%d", &n, &mod) != EOF) {
        init();
        printf("%lld\n", dp[n]);
    }
    return 0;
}
 
 
/*
3 1000000000
100000 1000000000
 
507109376
*/
View Code

E - Removal

题目大意:给你 n 个数, 每个数在1 - k 之间,现在让你删除 m 个数,问你最后有多少种序列。

思路:存在重复的问题,对于同一个序列我们只记录最靠前的一个,我们用nx[ i ][ j ]表示 i 后边第一个j 的位置。

可以得到dp方程: 每一个dp[ i ][ j ] 可以转移到 dp[ nx[ i ][ k ] ][ j + nx[ i ][ k ] -  i - 1]

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define pii pair<int, int>
#define y1 skldjfskldjg
#define y2 skldfjsklejg

using namespace std;

const int N = 1e5 + 7;
const int M = 1e5 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 +7;

int n, m, up, a[N], mp[11], nx[N][11], dp[N][11];

void init() {
    memset(mp, 0, sizeof(mp));
    for(int i = 0; i <= n; i++)
        for(int j = 0; j <= 10; j++)
            dp[i][j] = nx[i][j] = 0;
}

void add(int &a, int b) {
    a += b; if(a >= mod) a -= mod;
}
int main() {

    while(scanf("%d%d%d", &n, &m, &up) != EOF) {

        init();

        for(int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
        }

        for(int i = n; i >= 0; i--) {
            for(int j = 1; j <= up; j++) {
                nx[i][j] = mp[j];
            }
            mp[a[i]] = i;
        }

        dp[0][0] = 1;
        for(int i = 0; i < n; i++) {
            for(int j = 0; j <= m; j++) {

                if(!dp[i][j]) continue;

                for(int k = 1; k <= up; k++) {
                    int pos = nx[i][k];

                    if(pos && j + pos - i - 1 <= m) {
                        add(dp[pos][j + pos - i - 1], dp[i][j]);
                    }
                }
            }
        }

        int ans = 0;
        for(int i = 1; i <= n; i++) {
            int j = n - i;
            if(j <= m) add(ans, dp[i][m - j]);
        }

        printf("%d\n", ans);
    }
    return 0;
}


/*
3 2 2
1 2 1
4 2 2
1 2 1 2
*/
View Code

猜你喜欢

转载自www.cnblogs.com/CJLHY/p/9340074.html
今日推荐