[NOIP2024] 遗失的赋值题解

题目描述

小 F 有 n 个变量 x1​,x2​,…,xn​。每个变量可以取 1 至 v 的整数取值。

小 F 在这 n 个变量之间添加了 n−1 条二元限制,其中第 i(1≤i≤n−1)条限制为:若 xi​=ai​,则要求 xi+1​=bi​,且 ai​ 与 bi​ 为 1 到 v 之间的整数;当 xi​=ai​ 时,第 i 条限制对 xi+1​ 的值不做任何约束。除此之外,小 F 还添加了 m 条一元限制,其中第 j(1≤j≤m)条限制为:xcj​​=dj​。

小 F 记住了所有 cj​ 和 dj​ 的值,但把所有 ai​ 和 bi​ 的值都忘了。同时小 F 知道:存在给每一个变量赋值的方案同时满足所有这些限制。

现在小 F 想知道,有多少种 ai​,bi​(1≤i≤n−1)取值的组合,使得能够确保至少存在一种给每个变量 xi​ 赋值的方案可以同时满足所有限制。由于方案数可能很大,小 F 只需要你输出方案数对 109+7 取模的结果。

输入格式

本题包含多组测试数据

输入的第一行包含一个整数 T,表示测试数据的组数。

接下来包含 T 组数据,每组数据的格式如下:

第一行包含三个整数 n,m,v,分别表示变量个数、一元限制个数和变量的取值上限。

接下来 m 行,第 j 行包含两个整数 cj​,dj​,描述一个一元限制。

输出格式

对于每组测试数据输出一行,包含一个整数,表示方案数对 109+7 取模的结果。

输入输出样例

输入 #1复制

3
2 1 2
1 1
2 2 2
1 1
2 2
2 2 2
1 1
1 2

输出 #1复制

4
3
0

说明/提示

【样例 1 解释】

  • 对于第一组测试数据,所有可能的 (a1​,b1​) 取值的组合 (1,1),(1,2),(2,1),(2,2) 都满足限制。例如,(a1​,b1​)=(1,1) 时,(x1​,x2​)=(1,1) 满足所有限制,而 (a1​,b1​)=(2,2) 时,(x1​,x2​)=(1,1) 与 (x1​,x2​)=(1,2) 均满足所有限制。
  • 对于第二组测试数据,只有 (x1​,x2​)=(1,2) 一种可能的变量赋值,因此只有 (a1​,b1​)=(1,1) 不满足限制,其余三种赋值均满足限制。
  • 对于第三组测试数据,不存在一种变量赋值同时满足 x1​=1 和 x1​=2,因此也不存在满足限制的 (a1​,b1​)。

【样例 2】

见选手目录下的 assign/assign2.in 与 assign/assign2.ans

该样例共有 10 组测试数据,其中第 i(1≤i≤10)组测试数据满足数据范围中描述的测试点 i 的限制。

【样例 3】

见选手目录下的 assign/assign3.in 与 assign/assign3.ans

该样例共有 10 组测试数据,其中第 i(1≤i≤10)组测试数据满足数据范围中描述的测试点 i+10 的限制。

【数据范围】

对于所有的测试数据,保证:

  • 1≤T≤10,
  • 1≤n≤109,1≤m≤105,2≤v≤109,
  • 对于任意的 j(1≤j≤m),都有 1≤cj​≤n,1≤dj​≤v。
测试点n≤m≤v≤特殊性质
1,2662
399
4,51212
61031103
7105105
8,9109109
10103103103A
11104104104
12105105105
13104103104B
14106104106
15,16109105109
17104103104
18106104106
19,20109105109

特殊性质 A:保证 m=n,且对于任意的 j(1≤j≤m),都有 cj​=j。

特殊性质 B:保证 dj​=1。

附件下载

assign.zip1.44MB

思路

组合数学,直接取出不合法即可。

代码见下

#include<bits/stdc++.h>
using namespace std;
long long t,n,m,vv,c[100005],d[100005],as[100005],cc[100005],lk=1,mod=1e9+7;
map<long long,long long> mp;
long long pow2(long long a1,long long b1,long long m1){
    long long c1=1;
    a1=a1%m1;
    while(b1!=0){
        if(b1%2==1){
            c1=c1*a1%m1;
        }
        a1=a1*a1%m1;
        b1/=2;
    }
    return c1;
}
int main(){
    cin>>t;
    while(t--){
        cin>>n>>m>>vv;
        lk=1;
        mp.clear();
        for(int i=1;i<=m;i++){
            cin>>c[i]>>d[i];
            if(mp[c[i]]!=0&&mp[c[i]]!=d[i]){
                lk=0;
            }
            mp[c[i]]=d[i];
        }
        if(lk==0){
            cout<<lk<<endl;
        }
        else{
            sort(c+1,c+m+1);
            cc[0]=0;
            for(int i=1;i<=m;i++){
                if(i==1||c[i]!=c[i-1]){
                    cc[++cc[0]]=c[i];
                }
            }
            m=cc[0];
            for(int i=1;i<=m;i++){
                c[i]=cc[i];
            }
            c[0]=1;
            for(int i=1;i<=m;i++){
                if(i!=1){
                    lk=lk*((pow2(vv*vv%mod,c[i]-c[i-1],mod)-pow2(vv%mod,c[i]-c[i-1]-1,mod)*(vv-1)%mod+mod)%mod)%mod;
                    //cout<<i<<" "<<((pow2(vv*vv%mod,c[i]-c[i-1],mod)-pow2(vv*vv%mod,c[i]-c[i-1]-1,mod)*(vv-1)%mod+mod)%mod)%mod<<endl;
                }
                else{
                    lk=lk*(pow2(vv*vv%mod,c[i]-c[i-1],mod))%mod;
                }   
                
            }
            lk=lk*(pow2(vv*vv%mod,n-c[m],mod))%mod;
            cout<<lk<<endl;
        }
    }
    return 0;
}

posted @ 2025-10-13 15:34  bz02_2023f2  阅读(1)  评论(0)    收藏  举报  来源