容易题 呵tui~
毒瘤数学题
思路
我们考虑没有限制元素的情况,每个集合都是1~n
a
1
∗
b
1
∗
.
.
.
∗
m
1
+
a
1
∗
b
1
∗
.
.
.
∗
m
2...
a_1*b_1*...*m_1+a1*b_1*...*m2...
a1∗b1∗...∗m1+a1∗b1∗...∗m2...
发现可以合并成
(
a
1
+
a
2
+
.
.
.
+
a
n
)
∗
(
b
1
+
b
2
+
.
.
.
+
b
n
)
∗
.
.
.
∗
(
m
1
+
m
2
+
.
.
.
+
m
n
)
(a_1+a_2+...+a_n)*(b_1+b_2+...+b_n)*...*(m_1+m_2+...+m_n)
(a1+a2+...+an)∗(b1+b2+...+bn)∗...∗(m1+m2+...+mn)
没有限制就是相当于每次在每个括号里拿一个元素出来,乘到一起,然后加起来,那么答案就是
(
n
∗
(
n
+
1
)
2
)
m
(\frac{n*(n+1)}{2})^m
(2n∗(n+1))m
那么有限制的情况?
就相当于在一些括号里删除一些元素,也就是说一些括号的和不变,一些变小,我们发现最多有1e5个括号变小,所以把这些变小的括号先拎出来,用快速幂计算剩余的没有变化的括号,然后暴力求出变小的括号变小后的值,再依次乘到答案里就行了
代码
//By AcerMo
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define lli long long int
using namespace std;
const lli mod=1e9+7;
const int M=100500;
struct lim{lli x,y;}q[M];
lli n,m,e;
lli tp[M],cnt=0;
inline bool cmp(lim a,lim b)
{
if (a.x!=b.x) return a.x<b.x;
return a.y<b.y;
}
inline lli fpow(lli x,lli y)
{
lli z=1;
for (;y;x=(x*x)%mod,y>>=1)
if (y&1) z=(z*x)%mod;
return z;
}
signed main()
{
cin>>n>>m>>e;
for (int i=1;i<=e;i++)
scanf("%lld%lld",&q[i].x,&q[i].y);
lli s=(n*(n+1)>>1LL)%mod;
sort(q+1,q+e+1,cmp);
q[0].x=q[1].x-1;q[0].y=q[1].y-1;
for (int i=1;i<=e;i++)
{
if (q[i].x!=q[i-1].x) tp[++cnt]=s;
else if (q[i].y==q[i-1].y) continue;
tp[cnt]=(tp[cnt]-q[i].y+mod)%mod;
}
lli ans=fpow(s,m-cnt);
for (int i=1;i<=cnt;i++)
ans=(ans*tp[i]+mod)%mod;
cout<<ans;
return 0;
}