zoukankan      html  css  js  c++  java
  • 6439. 【GDOI2020模拟01.17】小 ω 数排列

    题目描述

    Description

    Input

    Output

    Sample Input
    Sample Input1
    4 10
    3 6 2 9

    Sample Input2
    8 35
    3 7 1 5 10 2 11 6

    Sample Output
    Sample Output1
    6

    【样例 1 解释】
    共有 6 个排列符合条件,它们是 (1, 3, 2, 4),(2, 4, 1, 3),(3, 1, 2, 4),(3, 1, 4, 2),(4, 2, 1, 3),(4, 2, 3, 1)。

    Sample Output2
    31384

    Data Constraint

    题解

    原题:LOJ#2743. 「JOI Open 2016」摩天大楼

    吼题

    显然题目所计算的是一个折线的总长

    由于不好从左往右放,所以考虑从下往上放(ai从小到大)

    (f[i][j][k][l=0/1/2])表示放了(a[1sim i]),形成了(j)段,折线在(y=ai)这条线下的长度之和为(k),有(l)段和边界相连

    那么当前段的边界个数即为(2j-l),也就是说从(a[i])推到(a[i+1])(k)会增加((a[i+1]-a[i])*(2j-l))

    分类讨论新加的(a[i+1])会放到哪里,那么有五种情况:

    ①新开一段:(j+1),方案数(j+1-l)

    ②把某两段相连:(j-1),方案数(j-1)

    ③和某一段相连:(j)不变,方案数(2j-l)

    ④和头/尾相连:(j+1,l+1),方案数(2-l)

    ⑤把头/尾和最靠近的一段相连:(j)不变,(l+1),方案数(2-l)

    最后答案为(sum{f[n][1][0sim L][2]})

    code

    #include <algorithm>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #define fo(a,b,c) for (a=b; a<=c; a++)
    #define fd(a,b,c) for (a=b; a>=c; a--)
    #define add(a,b) a=((a)+(b))%1000000007
    #define mod 1000000007
    #define file
    using namespace std;
    
    int a[1001];
    long long f[101][101][1001][3];
    int n,L,i,j,k,l,s;
    long long ans;
    
    int main()
    {
    	freopen("count.in","r",stdin);
    	#ifdef file
    	freopen("count.out","w",stdout);
    	#endif
    	
    	scanf("%d%d",&n,&L);
    	fo(i,1,n)
    	scanf("%d",&a[i]);
    	
    	if (n==1)
    	{
    		printf("1
    ");
    		return 0;
    	}
    	
    	sort(a+1,a+n+1);
    	
    	f[1][1][0][0]=1;
    	f[1][1][0][1]=2;
    	
    	fo(i,1,n-1)
    	{
    		fo(j,1,n)
    		{
    			fo(k,0,L)
    			{
    				fo(l,0,2)
    				if (f[i][j][k][l] && k+(2*j-l)*(a[i+1]-a[i])<=L)
    				{
    					s=k+(2*j-l)*(a[i+1]-a[i]);
    					
    					add(f[i+1][j+1][s][l],f[i][j][k][l]*(j+1-l));
    					add(f[i+1][j-1][s][l],f[i][j][k][l]*(j-1));
    					add(f[i+1][j][s][l],f[i][j][k][l]*(2*j-l));
    					if (l<2)
    					{
    						add(f[i+1][j+1][s][l+1],f[i][j][k][l]*(2-l));
    						add(f[i+1][j][s][l+1],f[i][j][k][l]*(2-l));
    					}
    				}
    			}
    		}
    	}
    	
    	fo(k,0,L)
    	add(ans,f[n][1][k][2]);
    	
    	printf("%lld
    ",ans);
    	
    	fclose(stdin);
    	fclose(stdout);
    	
    	return 0;
    }
    
  • 相关阅读:
    C语言文法
    实验一
    词法分析
    py中文词频统计
    py字符串练习
    py画了个国旗
    熟悉常用的Linux操作
    大数据概述
    实验三、 递归下降分析程序实验
    简易c语言LL(1)文法
  • 原文地址:https://www.cnblogs.com/gmh77/p/12208133.html
Copyright © 2011-2022 走看看