专栏文章

P11362 [NOIP2024] 遗失的赋值 解题报告

个人记录参与者 1已保存评论 1

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
1 条
当前快照
1 份
快照标识符
@miqkivaw
此快照首次捕获于
2025/12/04 06:18
3 个月前
此快照最后确认于
2025/12/04 06:18
3 个月前
查看原文
https://www.luogu.com.cn/problem/P11362

part1

n,m<=12,v<=2n,m<=12,v<=2
暴力搜索即可,可能的二元限制不会太多

part2

m=1m=1
注意到所有二元限制都满足要求
ans=(vv)(n1)ans=(v*v)^{(n-1)}

part3

特殊性质A
每个位置都有数,不合法的情况只有(ci,d!=di)(c_i,d!=d_i)

part4

特殊性质B
没啥想法
相比于正解,这档分让你不用考虑一元限制之间的矛盾

part5

正解
先判断一元限制之间是否有矛盾
然后运用part3part3中正难则反的思想,对于相邻的两个一元限制,不合法的情况形如:
d1v1,v1v2,v2v3,......,v(t1)d!=d2d1 v1,v1 v2,v2 v3,......,v(t-1) d!=d2
vt1(v1)v^{t-1}*(v-1)
总共情况有(vv)2t(v*v)^{2t}
把每一段乘起来,再用part2part2,把开头和结尾乘起来
然后就切掉了

AC code

CPP
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int mod=1e9+7;
map<int,int> mp;
vector<int> a;
ll qpow(ll x,ll p){
	if(p==0) return 1;
	if(p%2==1) return x*qpow(x,p-1)%mod;
	ll t=qpow(x,p/2);
	return t*t%mod;
}
void solve(){
	mp.clear();
	a.clear();
	bool flag=false;
	int n,m;ll v;
	cin>>n>>m>>v;
	
	for(int i=1;i<=m;i++){
		int c,d;cin>>c>>d;
		if(mp[c]){
			if(d!=mp[c]){
				flag=true;
				break;
			}
		}
		else{
			mp[c]=d;
			a.push_back(c);
		}
	}
	if(flag){
		cout<<0<<endl;
		return;
	}
	sort(a.begin(),a.end());
	int sz=a.size();
	ll ans=1;
	for(int i=1;i<sz;i++){
		int t=a[i]-a[i-1];//二元限制个数 
		/*
		d1 v1
		v1 v2
		v2 v3
		...
		v(t-1) d!=d2
		v^(t-1)
		*/
		int tmp=qpow(v,t-1)*(v-1)%mod;//不合法 
		ans=(qpow(v,2*t)-tmp+mod)%mod*ans%mod;
	}	
	//开头
	if(a[0]>1) ans=qpow(v*v%mod,a[0]-1)*ans%mod;
	//结尾
	if(a[sz-1]<n) ans=qpow(v*v%mod,n-a[sz-1])*ans%mod;
	
	cout<<ans<<endl;
}
int main(){
	//freopen("in.in","r",stdin);
	ios::sync_with_stdio(0);
	cin.tie(0);
	
	int T;cin>>T;
	while(T--) solve();
	return 0;
}

评论

1 条评论,欢迎与作者交流。

正在加载评论...