[NOIP2024] 遗失的赋值

[NOIP2024] 遗失的赋值

首先考虑特殊情况,什么时候会无解,很明显当两个一元约束约束了同一个位置并且d值不同,那么必然是无解的,直接输出0就行

对与一般情况,我们一元约束的d值很明显是无用的,我们只用管c值就行,因为我们统计的是合法方案数,所以不论一元约束的d值是多少,对于答案的贡献是一定的

我们可以对一元约束按c值排序,可以将c值作为左右端点将序列分为m+1个区间,规定区间左端点受一元约束,右端点不受约束,即第i个区间的范围为

\[\ \ \ \ \ \ \ \ \ \ \ \ \ i=1:[1,c_1) \]

\[\ \ \ \ \ i=m+1:[c_m,n] \]

\[1<i<m+1:[c_{i-1},c_i] \]

对于第一个区间(即左端不受一元约束的区间)中\(i\in[1,c_0-1]\) 时的 \(a_i\)\(b_i\) 可以随便(夏季八)填,可以直接为答案产生 \(v ^{(c_0-1)*2}\)的贡献

对于第二个区间及以后,定义区间长度\(x=c_i-c_{i-1}\)我们从左端点即受约束的点开始考虑,对于\(c_{i-1}\)的位置有两种情况,要么\(a_{c_{i-1}}\not=d_{i-1}\)此时\([c_{i-1}+1,c_i-1]\)的位置都不受约束,可以夏季八填,此时a有v-1中填法,对于之后的\(2x-1\)个位置,有\(v^{2x-1}\)种填法,所以对答案的贡献为\((v-1)*v^{2x-1}\)
要么\(a_{c_{i-1}}=d_{i-1}\)此时a只有一中填法,b有v种填法,但此时对于\(c_{i-1}\)位置的约束会传递到\(c_{i-1}+1\)位置,我们需要对下一个位置分讨,重复这一过程,直到我们将约束传递到右端点,此时右端点的b只有一中填法,所以,一个区间的贡献为:

\[(v-1)*v^{2x-1} \]

\[v*(v-1)*v^{2x-3} \]

\[v*v*(v-1)*v^{2x-5} \]

\[. \]

\[. \]

\[. \]

\[v*v*...*v(共x-1个) \]

将左右两边的v合并,将式子合并即为\(\sum _{i=1} ^{i<=x} (v-1)*v^{2x-i} +v^{x-1}\)
将(v-1)拆开,我们发现中间的几项抵消掉后只剩下\(v^{2x}+v^{x-1}-v^x\)
我们只需要写个快速幂计算贡献即可
ACcode:

using namespace std;
#define ll long long
#define mod 1000000007 
#define MAXN 100010
inline ll read(){
	ll x=0,f=1;
	char c=getchar();
	while(c<'0'||c>'9'){
		if(c=='-')f=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9'){
		x=x*10+c-'0';
		c=getchar();
	}
	return x*f;
}
struct node{
	ll c,d;
};
bool cmp(node a,node b){
	return a.c<b.c;
}
struct node_dsu{
	ll siz,p[MAXN];
	node q[MAXN];
	void insert(node a){
		q[++siz]=a;
	}
	bool mk(){
		sort(q+1,q+1+siz,cmp);
		ll _siz=0;
		for(int i=1;i<=siz;i++){
			if(q[i].c==q[i+1].c){
				if(q[i].d!=q[i+1].d)return false;
				continue;
			}
			p[++_siz]=q[i].c;
			q[i].c=q[i].d=0;
		}
		siz=_siz;
		return true;
	}
	void clear(){
		for(int i=1;i<=siz;i++)p[i]=0;
		siz=0;
	}
};
ll T,n,m,v,ans=1;
node_dsu dsu;
ll ksm(ll ds,ll zs){
	ll now=1;
	while(zs>0){
		if(zs&1)now=(now*ds)%mod;
		ds=(ds*ds)%mod;
		zs/=2;
	}
	return now;
}

int main(){
	T=read();
	while(T--){
		ans=1;
		dsu.clear();
		n=read(),m=read(),v=read();
		for(int i=1;i<=m;i++){
			dsu.insert((node){read(),read()});
		}
		if(dsu.mk()==false){
			cout<<"0\n";
			continue;
		}
		ans=ksm(v,2*(dsu.p[1]-1));
		for(int i=1;i<dsu.siz;i++){
			ll l=dsu.p[i+1]-dsu.p[i];
			ans=ans*(ksm(v,l*2)%mod+mod-ksm(v,l)+ksm(v,l-1))%mod;
		}
		ans=ans*ksm(v,(n-dsu.p[dsu.siz])*2)%mod;
		cout<<ans<<endl;
	}
	return 0;
}
posted @ 2024-12-06 21:35  flyfreemrn  阅读(27)  评论(0)    收藏  举报