• P7961 [NOIP2021] 数列


    [NOIP2021] 数列

    题目描述

    给定整数 n , m , k n, m, k n,m,k,和一个长度为 m + 1 m + 1 m+1 的正整数数组 v 0 , v 1 , … , v m v_0, v_1, \ldots, v_m v0,v1,,vm

    对于一个长度为 n n n,下标从 1 1 1 开始且每个元素均不超过 m m m 的非负整数序列 { a i } \{a_i\} {ai},我们定义它的权值为 v a 1 × v a 2 × ⋯ × v a n v_{a_1} \times v_{a_2} \times \cdots \times v_{a_n} va1×va2××van

    当这样的序列 { a i } \{a_i\} {ai} 满足整数 S = 2 a 1 + 2 a 2 + ⋯ + 2 a n S = 2^{a_1} + 2^{a_2} + \cdots + 2^{a_n} S=2a1+2a2++2an 的二进制表示中 1 1 1 的个数不超过 k k k 时,我们认为 { a i } \{a_i\} {ai} 是一个合法序列。

    计算所有合法序列 { a i } \{a_i\} {ai} 的权值和对 998244353 998244353 998244353 取模的结果。

    输入格式

    输入第一行是三个整数 n , m , k n, m, k n,m,k

    第二行 m + 1 m + 1 m+1 个整数,分别是 v 0 , v 1 , … , v m v_0, v_1, \ldots, v_m v0,v1,,vm

    输出格式

    仅一行一个整数,表示所有合法序列的权值和对 998244353 998244353 998244353 取模的结果。

    样例 #1

    样例输入 #1

    5 1 1
    2 1
    
    • 1
    • 2

    样例输出 #1

    40
    
    • 1

    样例 #2

    样例输入 #2

    见附件中的 sequence/sequence2.in
    
    • 1

    样例输出 #2

    见附件中的 sequence/sequence2.ans
    
    • 1

    提示

    【样例解释 #1】

    由于 k = 1 k = 1 k=1,而且由 n ≤ S ≤ n × 2 m n \leq S \leq n \times 2^m nSn×2m 知道 5 ≤ S ≤ 10 5 \leq S \leq 10 5S10,合法的 S S S 只有一种可能: S = 8 S = 8 S=8,这要求 a a a 中必须有 2 2 2 0 0 0 3 3 3 1 1 1,于是有 ( 5 2 ) = 10 \binom{5}{2} = 10 (25)=10 种可能的序列,每种序列的贡献都是 v 0 2 v 1 3 = 4 v_0^2 v_1^3 = 4 v02v13=4,权值和为 10 × 4 = 40 10 \times 4 = 40 10×4=40

    【数据范围】

    对所有测试点保证 1 ≤ k ≤ n ≤ 30 1 \leq k \leq n \leq 30 1kn30 0 ≤ m ≤ 100 0 \leq m \leq 100 0m100 1 ≤ v i < 998244353 1 \leq v_i < 998244353 1vi<998244353

    测试点 n n n k k k m m m
    1 ∼ 4 1 \sim 4 14 = 8 =8 =8 ≤ n \leq n n = 9 =9 =9
    5 ∼ 7 5 \sim 7 57 = 30 =30 =30 ≤ n \leq n n = 7 =7 =7
    8 ∼ 10 8 \sim 10 810 = 30 =30 =30 ≤ n \leq n n = 12 =12 =12
    11 ∼ 13 11 \sim 13 1113 = 30 =30 =30 = 1 =1 =1 = 100 =100 =100
    14 ∼ 15 14 \sim 15 1415 = 5 =5 =5 ≤ n \leq n n = 50 =50 =50
    16 16 16 = 15 =15 =15 ≤ n \leq n n = 100 =100 =100
    17 ∼ 18 17 \sim 18 1718 = 30 =30 =30 ≤ n \leq n n = 30 =30 =30
    19 ∼ 20 19 \sim 20 1920 = 30 =30 =30 ≤ n \leq n n = 100 =100 =100

    Sol

    表示当前考虑到第i位,已经放了j个数,当前已经有了k个1,并且这一位还存储的1的个数p
    考虑从这一个位置开始向下转移,考虑枚举这一个位置该放置1的个数,然后向下转移
    f [i+1][j+t][k+(t+p)%2][(t+p)/2]+= f[i][j][k][p]*C[n-j][t]*pow(a[i],t)%mod
    考虑答案在什么时候出现,显然就是,f[m+1][n][0~k][p] 并且满足 p向上进位之后加上k还是小于输入的k

    #include
    #define I inline
    #define LL long long
    #define inf 0x3f3f3f3f
    #define LB long double
    #define RI register int
    #define N 32
    #define debug puts("debug");
    #define M 150
    #define mod 998244353
    #define memeory cout<<abs(&me2-&me1)/1024./1024<<"MB"<<endl;
    using namespace std;
    I LL read()
    {
    	LL res=0,f=1;char ch=getchar();
    	while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
    	while(isdigit(ch))res=(res<<1)+(res<<3)+(ch&15),ch=getchar();
    	return res*f;
    }
    LL C[M][M],n,m,K,a[M],f[M][N][N][N];
    //表示当前考虑到第i位,已经放了j个数,当前已经有了k个1,并且这一位还存储的1的个数p 
    //考虑从这一个位置开始向下转移,考虑枚举这一个位置该放置1的个数,然后向下转移
    //f [i+1][j+t][k+(t+p)%2][(t+p)/2]+= f[i][j][k][p]*C[n-j][t]*pow(a[i],t)%mod
    //考虑答案在什么时候出现,显然就是,f[m+1][n][0~k][p] 并且满足 p向上进位之后加上k还是小于输入的k
    I void getC(){
    	for(RI i=0;i<=n;i++)C[i][0]=1;
    	for(RI i=1;i<=n;i++)
    	for(RI j=1;j<=i;j++)
    	C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
    	
    } 
    I int pop(int x){
    	int ans=0;while(x)ans+=(x&1),x>>=1;
    	return ans;
    }
    I LL qpow(LL ds,LL zs){
    	LL ans=1;while(zs){
    		if(zs&1)ans=(ans*ds)%mod;
    		ds=(ds*ds)%mod;zs>>=1;
    	}return ans;
    }
    int main()
    {
    	n=read();m=read();K=read();getC();
    	for(RI i=0;i<=m;i++)a[i]=read();f[0][0][0][0]=1;
    	for(RI i=0;i<=m;i++){
    		for(RI j=0;j<=n;j++){
    			for(RI k=0;k<=K;k++){
    				for(RI p=0;p<=n;p++){
    					for(RI t=0;t+j<=n;t++){
    						f[i+1][j+t][k+(t+p)%2][(t+p)/2]
    						+=f[i][j][k][p]*C[n-j][t]%mod*qpow(a[i],t)%mod;
    						f[i+1][j+t][k+(t+p)%2][(t+p)/2]%=mod;
    					}
    				}
    			}
    		}
    	}
    	LL num=0;for(RI k=0;k<=K;k++)for(RI p=0;p<=n;p++)if(k+pop(p)<=K)num+=f[m+1][n][k][p],num%=mod;
    	printf("%lld\n",num%mod);return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
  • 相关阅读:
    后端 | 如何卸载 setup.py 安装 python 包 | Python
    【C++】运算符重载 ⑤ ( 一元运算符重载 | 使用 成员函数 实现 前置 ++ 自增运算符重载 | 使用 成员函数 实现 前置 - - 自减运算符重载 )
    Unity API详解——GameObject类
    FreeRTOS_事件标志组
    柯桥托业TOEIC考试和PETS哪个含金量高?
    MySQL存储引擎
    初步认识系统调用
    QT 工具栏设置
    新的抓包神器,完全免费,支持多平台!
    基于深度学习的YOLO目标检测研究-附Matlab代码
  • 原文地址:https://blog.csdn.net/yhhy666/article/details/127885375