我是靠谱客的博主 坚定裙子,最近开发中收集的这篇文章主要介绍【Gym - 101991K】Khoshaf(动态规划),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

Gym - 101991K

题意

给定 N , K , L , R N,K,L,R N,K,L,R,构造一个长度为 N N N的数列,每个数在 [ L , R ] [L,R] [L,R]区间内,且和为3的倍数的区间恰好为 K K K个,求方案数。

题解

首先转换题意,和为3的倍数即和对3取模等于0,可以先考虑每个位置放0/1/2的方案数。
然后设计状态,设 d p [ n ] [ k ] [ x ] [ y ] [ z ] [ 0 / 1 / 2 ] dp[n][k][x][y][z][0/1/2] dp[n][k][x][y][z][0/1/2],其中 n n n是构造数列长度、 k k k是和为3的倍数的区间数、 x / y / z x/y/z x/y/z 分别是和为 0 / 1 / 2 0/1/2 0/1/2 的前缀数量、最后是区间总和模3的值。此时状态数有 N 4 K N^4K N4K 那么大,显然是不可取的。通过计算可以发现, n = x + y + z n=x+y+z n=x+y+z,且 k = [ x ⋅ ( x + 1 ) + y ⋅ ( y − 1 ) + z ⋅ ( z − 1 ) ] / 2 k=[x·(x+1)+y·(y-1)+z·(z-1)]/2 k=[x(x+1)+y(y1)+z(z1)]/2(前缀和相减得到区间和),因此前两维是不需要的。此时状态数仍然有 N 3 N^3 N3 那么多。通过上面的式子还可以发现, x / y / z x/y/z x/y/z 并没有必要枚举到 N N N 那么大,因为 2 ⋅ k = x ⋅ ( x + 1 ) + y ⋅ ( y − 1 ) + z ⋅ ( z − 1 ) > x ⋅ ( x − 1 ) > ( x − 1 ) 2 2·k=x·(x+1)+y·(y-1)+z·(z-1)>x·(x-1)>(x-1)^2 2k=x(x+1)+y(y1)+z(z1)>x(x1)>(x1)2,即 x < 2 ⋅ k + 1 < 143 x<sqrt{2·k}+1<143 x<2k +1<143 y / z y/z y/z同理。
之后考虑转移。首先求出 [ L , R ] [L,R] [L,R]区间内对3取模等于 0 / 1 / 2 0/1/2 0/1/2 的数字的数量,记为 c [ 0 / 1 / 2 ] c[0/1/2] c[0/1/2]。这样就可以写出转移方程:
d p [ x ] [ y ] [ z ] [ 0 ] = ∑ w = 0 2 d p [ x − 1 ] [ y ] [ z ] [ w ] ⋅ c [ ( 0 − w ) % 3 ] dp[x][y][z][0]=sum_{w=0}^{2} dp[x-1][y][z][w]·c[(0-w)%3] dp[x][y][z][0]=w=02dp[x1][y][z][w]c[(0w)%3]
d p [ x ] [ y ] [ z ] [ 1 ] = ∑ w = 0 2 d p [ x ] [ y − 1 ] [ z ] [ w ] ⋅ c [ ( 1 − w ) % 3 ] dp[x][y][z][1]=sum_{w=0}^{2} dp[x][y-1][z][w]·c[(1-w)%3] dp[x][y][z][1]=w=02dp[x][y1][z][w]c[(1w)%3]
d p [ x ] [ y ] [ z ] [ 2 ] = ∑ w = 0 2 d p [ x ] [ y ] [ z − 1 ] [ w ] ⋅ c [ ( 2 − w ) % 3 ] dp[x][y][z][2]=sum_{w=0}^{2} dp[x][y][z-1][w]·c[(2-w)%3] dp[x][y][z][2]=w=02dp[x][y][z1][w]c[(2w)%3]

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int M=1e9+7;

ll d[160][160][160][3];
int main(){
	ifstream fin("khoshaf.in");
	int T,n,k,l,r;
	fin>>T;
	while(T--){
		fin>>n>>k>>l>>r;
		if(n>400){
			cout<<"0n";
			continue;
		}
		int c[3]={(r-l+1)/3,(r-l+1)/3,(r-l+1)/3};
		if(l%3==r%3)c[l%3]++;
		if((l+1)%3==r%3)c[l%3]++,c[r%3]++;
		
		ll ans=0;
		memset(d,0,sizeof d);
		d[0][0][0][0]=1;
		for(int x=0;x<150;x++)if(x<=n){
			for(int y=0;y<150;y++)if(x+y<=n){
				for(int z=0;z<150;z++)if(x+y+z<=n){
					for(int w=0;w<3;w++){
						auto &dx=d[x][y][z][w];
						dx%=M;
						d[x+1][y][z][0]+=dx*c[(3-w)%3];
						d[x][y+1][z][1]+=dx*c[(4-w)%3];
						d[x][y][z+1][2]+=dx*c[(5-w)%3];
						if(x+y+z==n && x*(x+1)+y*(y-1)+z*(z-1)==k*2)
							ans+=dx;
					}
				}
			}
		}
		cout<<ans%M<<'n';
	}
	return 0;
}

最后

以上就是坚定裙子为你收集整理的【Gym - 101991K】Khoshaf(动态规划)的全部内容,希望文章能够帮你解决【Gym - 101991K】Khoshaf(动态规划)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(53)

评论列表共有 0 条评论

立即
投稿
返回
顶部