码迷,mamicode.com
首页 > 其他好文 > 详细

srm 531

时间:2015-06-03 17:36:02      阅读:172      评论:0      收藏:0      [点我收藏+]

标签:

300



Description

你有n种曲子,要搞出一个长度为p的歌曲序列,保证任意两首相同的曲子之间至少有m首其他曲子。求用全部n种曲子生成的歌曲序列种数mod109+7

Solution

考虑f[i][j]表示当前是序列的第i首歌,已经用了j种不同的曲子的方案数。考虑当前用新的曲子,则f[i][j]=f[i?1][j?1]?(n?j),考虑如果用之前的曲子,那么f[i][j]=f[i?1][j]?(j?m),因为不能和当前前面的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;
    }
};




srm 531

标签:

原文地址:http://blog.csdn.net/mlzmlz95/article/details/46348807

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!