NOIP2024 T2 题解

· · 题解

Div.2 C 级别唐氏题,考场上为什么调了 3h+ 还没调出来呢?连 newbie 都能场切这题,我真的是 CM 吗?

首先排序去重,如果遇到条件自己冲突的那方案数就是 0

按照已经确定的点将原序列 n 个位置划分为若干段,除了首段全部由不确定位置组成以外,每一段开头都是一个确定的位置。

#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;
}