NOIP2024 T2 题解
__vector__ · · 题解
Div.2 C 级别唐氏题,考场上为什么调了 3h+ 还没调出来呢?连 newbie 都能场切这题,我真的是 CM 吗?
首先排序去重,如果遇到条件自己冲突的那方案数就是
按照已经确定的点将原序列
- 首段不确定位置
这一段的a,b 随便填,只需要让x_i \neq a_i ,那么就显然是合法的。 - 除了首段,最后一段以外的段
这类段的特点是第一个位置是确定的,段最后的下一个位置也是确定的。
段的a,b 方案书可以通过总方案数减去不合法方案数得到,令长度为l 。
总方案数是v^{2l} 。
不合法方案如何构造呢?显然只能是本段通过一些a,b 的构造,强迫下一个确定位置的x 值不等于其给定值。
第一个位置有v 的方案数确定第二个位置的值,第二个位置同样有v 的方案数确定第三个位置的值。
以此类推,总共有v^{len-1} 的方案数确定本段最后一个位置的值。 本段最后一个位置总共有v-1 的方案数(a 值等于自己,b 值不等于下一个位置)。 所以,总的不合法方案数是v^{len-1}(v-1) 。 总合法方案数是v^{2len}-v^{len-1}(v-1) 。 - 最后一段
显然a,b 随便填。
#include <bits/stdc++.h>
using namespace std;
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define REP(i,a,b) for(int i=a;i>=b;i--)
#define pb push_back
#define mkpr make_pair
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef vector<int> vi;
template<class T>
void ckmx(T& a,T b){
a=max(a,b);
}
template<class T>
void ckmn(T& a,T b){
a=min(a,b);
}
template<class T>
T gcd(T a,T b){
return !b?a:gcd(b,a%b);
}
template<class T>
T lcm(T a,T b){
return a/gcd(a,b)*b;
}
#define gc getchar()
#define eb emplace_back
#define pc putchar
#define ep empty()
#define fi first
#define se second
#define pln pc('\n');
template<class T>
void wrint(T x){
if(x<0){
x=-x;
pc('-');
}
if(x>=10){
wrint(x/10);
}
pc(x%10^48);
}
template<class T>
void wrintln(T x){
wrint(x);
pln
}
template<class T>
void read(T& x){
x=0;
int f=1;
char ch=gc;
while(!isdigit(ch)){
if(ch=='-')f=-1;
ch=gc;
}
while(isdigit(ch)){
x=(x<<1)+(x<<3)+(ch^48);
ch=gc;
}
x*=f;
}
const ll mod=1e9+7;
int n,m,v;
pii lim[100005];
ll qpow(ll a,ll b){
// printf("qpow %lld %lld\n",a,b);
ll ret=1;
for(;b;a=a*a%mod,b>>=1){
if(b&1)ret=ret*a%mod;
}
// printf("ret %lld\n",ret);
return ret;
}
void solve(int id_of_test){
read(n);
read(m);
read(v);
FOR(i,1,m){
read(lim[i].fi);
read(lim[i].se);
}
sort(lim+1,lim+m+1);
m=unique(lim+1,lim+m+1)-lim-1;
FOR(i,1,m-1){
if(lim[i].fi==lim[i+1].fi){
if(lim[i].se!=lim[i+1].se){
puts("0");
return;
}
}
}
ll ans=1;
ans=ans*qpow(v,2*(lim[1].fi-1));
ans=ans*qpow(v,2*(n-lim[m].fi))%mod;
FOR(i,1,m-1){
ll res=qpow(v,2*(lim[i+1].fi-lim[i].fi));
// printf("pre %lld [%d,%d]\n",res,lim[i].fi,lim[i+1].fi);
res-=qpow(v,lim[i+1].fi-lim[i].fi-1)*(v-1)%mod;
// printf("fff %lld\n",res);
ans=ans*res%mod;
}
printf("%lld\n",(ans+mod)%mod);
}
int main()
{
int T;
read(T);
FOR(_,1,T){
solve(_);
}
return 0;
}