srm 531

300



Description

你有n 種曲子,要搞出一個長度爲p 的歌曲序列,保證任意兩首相同的曲子之間至少有m 首其他曲子。求用全部n 種曲子生成的歌曲序列種數mod109+7

Solution

考慮f[i][j] 表示當前是序列的第i 首歌,已經用了j種不同的曲子的方案數。考慮當前用新的曲子,則f[i][j]=f[i1][j1](nj) ,考慮如果用之前的曲子,那麼f[i][j]=f[i1][j](jm) ,因爲不能和當前前面的m首相同。

Code

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 105, M = 1e9 + 7;
int f[N][N];
void add(int &x, int y) {
    x += y;
    if (x >= M) x -= M;
}
class NoRepeatPlaylist {
    public:
    int numPlaylists(int n, int m, int p) {
        f[0][0] = 1;
        for (int i = 1; i <= p; ++i)
            for (int j = 1; j <= min(i, n); ++j) {
                f[i][j] = (LL)f[i - 1][j - 1] * (n - j + 1) % M;
                if (j > m)  add(f[i][j], (LL)f[i - 1][j] * (j - m) % M);
            }
        return f[p][n];
    }
};


500



Description:

給定一個鄰接矩陣表示的圖,初始你有1 個人標號爲1 , 每天所有人都會掛掉,然後生出其他人(有可能是自己,且個數可大於1)。問最後人數是否有限,如果有限輸出個數否則輸出1

Solution

首先我們求個傳遞閉包。然後我們可以發現如果第一個人經過一段時間可以生出第i 個人,而且第i 個人經過一段時間可以生出自己,且第i 個人不止生出一個人的話,顯然最後人數是無限的。
否則則是有限的,我們顯然經過有限次輪數人數一定不變。我隨手設了1000 次,但其實仔細分析下,在n 輪內其實答案就一定不在變化了。

Code:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 50, M = 1e9 + 7;
int d[N], a[N][N], g[N][N];
LL ans[2][N];
class MonsterFarm {
    public:
    int numMonsters(vector <string> transforms) {
        int n = transforms.size();
        for (int i = 0 ; i < n; ++i) {
            istringstream t(transforms[i]);
            for (int x; t >> x; ) {
                --x;
                ++a[i][x];
                ++d[i];
                g[i][x] = 1;
            }
        }
        for (int k = 0; k < n; ++k)
            for (int i = 0; i < n; ++i)
                for (int j = 0; j < n; ++j)
                    g[i][j] |= g[i][k] & g[k][j];
        bool ok = 0;
        for (int i = 0; i < n; ++i)
            if (g[0][i] && g[i][i] && d[i] > 1) ok = 1;
        if (ok) return -1;//inf
        queue<int> q;
        q.push(0);
        ans[0][0] = 1;
        for (int step = 1; step <= 1000; ++step) {
            memset(ans[1], 0, sizeof(ans[1]));
            for (int i = 0; i < n; ++i)
                for (int j = 0; j < n; ++j)
                    (ans[1][j] += g[i][j] * ans[0][i] * a[i][j] % M) %= M;
            for (int i = 0; i < n; ++i) ans[0][i] = ans[1][i];
        }
        LL t = 0;
        for (int i = 0; i < n; ++i) (t += ans[0][i]) %= M;
        return t;
    }
};




發佈了86 篇原創文章 · 獲贊 7 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章