国庆集训Day1

国庆集训Day1题解

T1 divide

题意:

\(n\)个数 \(a_1, a_2,..., a_n\) 有m个数\(b_1, b_2,..., b_n\)

\(a = a_1\times a_2\,\times ... \times \,a_n\)

\(b = b_1\times\,b_2 \times\,...\,\times\,b_n\)

判断\(a\)是否是\(b\)的倍数

输入:\(n,m\)

输出:\(Yes / No\)

做法:就是个一简单的质因数分解

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n, m;
int a[1010], b[1010];
int p[3][20]={};
void divid(int op, int x)
{
    if(x == 1) return;
    if(x == 2) p[op][1]++;
    if(x == 3) p[op][2]++;
    if(x == 4) p[op][1] += 2;
    if(x == 5) p[op][3]++;
    if(x == 6) {p[op][1]++; p[op][2]++;}
    return;
}
int main()
{
    freopen("divide.in","r",stdin);
    freopen("divide.out","w",stdout);
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++)
    {
        scanf("%d", &a[i]);
        divid(1, a[i]);
    }
    for(int i = 1; i <= m; i++)
    {
        scanf("%d", &b[i]);
        divid(2, b[i]);
    }
    for(int i = 1; i <= 3; i++)
    {
        if(p[1][i] >= p[2][i])continue;
        else
        {
            printf("No\n"); return 0;
        }
    }
    printf("Yes\n");
    return 0;
}
/*
样例:
输入:2 3
     6 6
     1 3 4
输出:Yes
*/

T2 graph

题意:

现在要生成一张n个点的有向图。要求满足:

1.若有\(a-> b\)的边,则有\(b->a\)的边

2.若有\(a->b\)的边和\(b->c\)的边,则有\(a->c\)的边

3.至少有一个点没有自环

求方案数。 由于结果可能较大,结果对\(m\)取模

输入:\(n,m\)

输出:答案

做法:

这道题除了题意比较坑以外,没有什么太大的难点。需要注意的是,按照题意,如果一个点所在的连通块大小大于或等于2,则该点一定有自环。

我的做法是:设\(f[i][0]\)表示\(i\)个点自由组合,且每个点都存在自环的方案数

\(f[i][1]\)表示\(i\)个点自由组合,且至少有\(1\)个点没有自环的方案数

我转移方程的方法有点独特,我是看\(1\)号点所在的连通块的点的个数进行转移,需要注意的是转移是需要讨论\(1\)号点是否孤立为一个点,若孤立,则有\(1\)号点自环和不自环的两种情况,需分别进行讨论,状态转移方程如下:

\(f[i][1]+=f[i - 1][1]\,\,\,\,1\)号点孤立且\(1\)号点存在自环

\(f[i][1] += f[i - 1][1] + f[i - 1][0]\,\,\,\,1\)号点孤立且\(1\)号点不存在自环,则其他点可以自环,可以不自环

\(f[i][1] +=\sum_{j=2}^{i} f[i - j][1]\times C_{i-1}^{j-1} \,\,\,\,\)计算\(1\)号点所在的连通块大小为\(j\)时的方案数

\(f[i][0]+=f[i-1][0]\,\,\,\,1\)号点孤立时只能自环

\(f[i][0]+=\sum_{j=2}^{i} f[i - j][0]\times C_{i-1}^{j-1} \,\,\,\,\)计算\(1\)号点所在的连通块大小为\(j\)时的方案数

组合数用杨辉三角就可以了。

老师讲的做法是把“第\(1\)个点”改成“第\(i\)个点”,其实写法是一样的,只是思路不同而已。

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
#define maxn 2010
#define ll long long
int n, mol;
ll f[maxn][2];//  1:符合题意 0:不符合题意 
ll C[maxn][maxn];
int main()
{
    freopen("graph.in", "r", stdin);
    freopen("graph.out", "w", stdout);
    scanf("%d%d", &n, &mol);
    for(int i = 0; i <= n; i++) C[i][0] = 1;
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= i; j++)
        {
            C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % mol;
        }
    }
/*  for(int i = 0; i <= n; i++)
    {
        for(int j = 0; j <= i; j++)
        printf("C[%d][%d] = %lld ", i, j, C[i][j]);
        printf("\n");
    }
*/
    f[1][1] = 1; f[1][0] = 1;
    for(int i = 2; i <= n; i++)
    {
        f[i][1] = (f[i][1] + f[i - 1][1] + f[i - 1][0] + f[i - 1][1]) % mol;
        f[i][0] = (f[i][0] + f[i - 1][0]) % mol;
        for(int j = 2; j < i; j++)
        {
//          f[i][1] = (f[i][1] + ( ( ( (C[i - 1][j - 1] * S[j - 1][j - 1]) % mol ) * ( (f[i - j][0] + f[i - j][1]) % mol) ) % mol)) % mol;                                               
            f[i][1] = (f[i][1] + (C[i - 1][j - 1] * f[i - j][1]) % mol) % mol;
            f[i][0] = (f[i][0] + (C[i - 1][j - 1] * f[i - j][0]) % mol) % mol;
        }
        f[i][0] = (f[i][0] + 1) % mol;
    }
//  for(int i = 1; i <= n; i++)
//  printf("f[%d][0] = %lld f[%d][1] = %lld\n", i, f[i][0], i, f[i][1]);
    printf("%lld\n", f[n][1]);
    return 0;
}             
/*
样例:
输入:2 5
输出:3
*/

T3 生成图

猜你喜欢

转载自www.cnblogs.com/Akaina/p/11615733.html
今日推荐