[BZOJ]容易题 [HAOI2012]

题目描述

为了使得大家高兴,小Q特意出个自认为的简单题(easy)来满足大家,这道简单题是描述如下:

有一个数列A已知对于所有的A[i]都是1~n的自然数,并且知道对于一些A[i]不能取哪些值,我们定义一个数列的积为该数列所有元素的乘积,要求你求出所有可能的数列的积的和 mod 1000000007的值,是不是很简单呢?呵呵!

输入输出格式

输入格式:

第一行三个整数n,m,k分别表示数列元素的取值范围,数列元素个数,以及已知的限制条数。

接下来k行,每行两个正整数x,y表示A[x]的值不能是y。

输出格式:

一行一个整数表示所有可能的数列的积的和对1000000007取模后的结果。如果一个合法的数列都没有,答案输出0。

输入输出样例

输入样例
 3 4 5
 1 1
 1 1
 2 2
 2 3
 4 3
输出样例
90

说明

样例解释

A[1]不能取1

A[2]不能去2、3

A[4]不能取3

所以可能的数列有以下12种

数列
2 1 1 1 2
2 1 1 2 4
2 1 1 4 4
2 1 2 2 8
2 1 3 1 6
2 1 3 2 12
3 1 1 1 3
3 1 1 2 6
3 1 2 1 6
3 1 2 2 12
3 1 3 1 9
3 1 3 2 18

30%的数据$$n \leq 4,m\leq 10,k \leq 10$$

另有20%的数据$$k=0$$

70%的数据$n \leq 1000,m \leq 1000,k \leq 1000$

100%的数据 $n \leq 10^9,m \leq 10^9,k \leq 10^5,1 \leq y \leq n,1 \leq x \leq m$

思路

数论

分类讨论:

对于$$k=0$$:

​ $$ans= (\sum _{i=1} ^n i)^m$$

对于$$k \neq 1$$

​ $$ans=P \times Q$$

​ 其中:

​ $$P=(\sum _{i=1} ^n i)-y(被限制的数字)$$

​ $$Q=(\sum _{i=1} ^n i)^{m-cnt};(cnt为被限制的位数)$$

注意:需要去重;负数取模

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
const int mod = 1e9 + 7;
ll n, k, m;
struct node { ll x; ll y; };
node a[maxn];
ll sum = 0;
ll sig[maxn];
ll ans = 0;

int cmp(node x, node y)
{
    return (x.x == y.x) ? (x.y < y.y) : (x.x < y.x);
}

ll powmod(ll a, ll b)
{
    ll ret = 1;
    while (b)
    {
        if (b & 1)    ret = ret*a %mod;
        a = a*a%mod;
        b >>= 1;
    }
    return ret;
}

int main()
{
    scanf("%lld %lld %lld", &n, &m, &k);
    sum = (1 + n)*n / 2 % mod;
    for (int i = 1; i <= k; i++)
    {
        scanf("%lld %lld", &a[i].x, &a[i].y);
    }
    sort(a + 1, a + k + 1, cmp);
    ll cnt = 0;
    for (int i = 1; i <= k; i++)
    {//去重
        if (a[i].x != a[i - 1].x)
            sig[++cnt] = sum;
        else
        {
            if (a[i].y == a[i - 1].y)    continue;
        }
        sig[cnt] = (sig[cnt] - a[i].y + mod) % mod;
    }
    ans += powmod(sum, m - cnt);
    for (int i = 1; i <= cnt; i++)
    {
        ans = (ans*sig[i] + mod) % mod;
    }
    printf("%lld\n", ans);
}

results matching ""

    No results matching ""