洛谷 P2220 [HAOI2012]容易题

洛谷 P2220 [HAOI2012]容易题

题目

为了使得大家高兴,小Q特意出个自认为的简单题(easy)来满足大家,这道简单题是描述如下:
有一个数列A已知对于所有的A[i]都是1~n的自然数,并且知道对于一些A[i]不能取哪些值,我们定义一个数列的积为该数列所有元素的乘积,要求你求出所有可能的数列的积的和 mod 1000000007的值,是不是很简单呢?呵呵!

输入 #1

3 4 5
1 1
1 1
2 2
2 3
4 3

输出 #1

90

说明/提示

样例解释

A[1]不能取1

A[2]不能去2、3

A[4]不能取3

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

数列 积

2 1 1 1 2

2 1 1 2 4

2 1 2 1 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<=4,m<=10,k<=10

另有20%的数据k=0

70%的数据n<=1000,m<=1000,k<=1000

100%的数据 n<=10^9 ,m<=109,k<=105,1<=y<=n,1<=x<=m

分析

这个题还是比较简单的,但我调了好长时间

根据提示,我们对每一位上的数用分配律,也就是让每一位可以取得的数相加,根据原理,让每一位上取得的数的和相乘即可。

比如样例第一位可以选2,3,第一位的和为5;第二位可以选1,和为1;第三位可以选1,2,3,和为6;第四位可以选1,2,和为3。所以答案为5 * 1 * 6 * 3 = 90

不过数据很大,我们可以用快速幂先把所有没有改变的位置上的数乘出来,最后再乘以剩余位上的数即可。

能模的地方都模上吧~~

代码

/*************************************************************************
	> File Name: nn.cpp
	> Author: LiuGeXian
	> Mail: [email protected] 
	> Created Time: 2020/5/13 11:49:32
 ************************************************************************/

#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
const int MOD = 1000000007;
const int maxn = 1e5 + 5;
typedef long long ll;
struct Node{
	int a, b;
}limit[maxn];
ll n, m, k, t;
ll num[maxn], ans;
bool cmp(Node a, Node b){
	if (a.a != b.a) return a.a < b.a;
	return a.b < b.b;
}
ll Pow(ll sum, ll k){
	ll ans = 1;
	sum %= MOD;
	while (k){
		if (k & 1) ans = (ans * sum) % MOD;
		sum = (sum * sum) % MOD;
		k >>= 1;
	}
	return ans % MOD;
}
int main(){
	scanf("%lld%lld%lld", &n, &m, &k);
	ll sum = 1LL * ((1 + n) * n / 2) % MOD;
	for (int i = 1; i <= k; i++){
		scanf("%d%d", &limit[i].a, &limit[i].b);
	}
	sort(limit + 1, limit + 1 + k, cmp);
	for (int i = 1; i <= k; i++){
		if (limit[i].a != limit[i-1].a) num[++t] = sum;
		else if (limit[i].b == limit[i-1].b) continue;
		num[t] -= limit[i].b;
		num[t] += MOD;
		num[t] %= MOD;
	}
	ans = Pow(sum, m - t) % MOD;
	for (int i = 1; i <= t; i++){
		ans = (ans * num[i]) % MOD;
		ans += MOD;
		ans %= MOD;
	}
	printf("%lld", ans % MOD);
	return 0;
}

猜你喜欢

转载自www.cnblogs.com/ghosh/p/12887946.html
今日推荐