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万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章