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[1\sim 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][0\sim 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\n");
        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\n",ans);

    fclose(stdin);
    fclose(stdout);

    return 0;
}

原文地址:https://www.cnblogs.com/gmh77/p/12208133.html

时间: 2024-11-07 23:32:30

6439. 【GDOI2020模拟01.17】小 ω 数排列的相关文章

【GDOI2020模拟01.17】小 ω 玩游戏 (容斥+EGF)

小 ω 正在玩一个游戏. 小 ω 有一个 n 行 m 列的网格,初始每个方格中都有数字 0.她需要执行 q 次操作,每次操作可以选择其中一个方格 (x, y),然后先将第 x 行的数全部 +1,接着将第 y 列的数全部 +1. 小 ω 想知道有多少种执行操作的方式能使最后的网格中有不超过 k 个奇数. 两种方式不同当且仅当存在某一步中选择的方格坐标不同. \(1<=n,m<=2e5,q<=10^{18}\) 考虑行列分开,对行,算出\(f(x)\)表示恰好x行奇数的方案数,对列同理,算出

6441. 【GDOI2020模拟01.17】小 ω 维护序列

Description Input Output 输出到标准输出流中. 若干行,对于每个操作 1 和操作 5,输出一个数表示答案. Sample Input Sample Input1 5 8 1 2 3 2 1 1 1 3 5 1 5 2 2 4 1 2 4 3 3 4 0 5 1 1 2 1 1 5 Sample Input2 10 15 5 4 3 5 4 1 5 4 3 1 2 8 580347 4 6 503576 1 2 5 5 8 11 1 2 6 4 7 565239 3 6 3

6442. 【GDOI2020模拟01.18】钩子

题目描述 Description Input Output Sample Input Sample Input1 3 1000000007 Sample Input2 4 1000000007 Sample Output Sample Output1 0 1 0 500000004 0 500000004 500000004 0 500000004 Sample Output2 0 500000004 500000004 0 333333336 166666668 166666668 33333

【GDOI2020模拟03.28】数二数(two) (计数动态规划):

? 先考虑如何判断一个询问集是否合法. 考虑询问一次\([l,r]\),能把\([1,l-1]∪[r+1,n]\)和\([l,r]\)区分开来. 现在定义一个块为一个没有被区分开极大的点集合. 当所有块的大小都是1的时候,这个方案就是合法. ? 性质: 1.一个块是由若干连续段组成,比如下面这样: 1112233111411 颜色为1的块由三段连续段. ? 2.块与块之间不会出现交叉的情况: 比如下面这样: 11122211122211 也就说两个块的关系,只有完全包含和互不相交两种. ? 设\

【NOIP2016提高A组模拟9.17】数格子

题目 分析 设表示每一行的状态,用一个4位的二进制来表示,当前这一行中的每一个位数对下一位有没有影响. 设\(f_{i,s}\)表示,做完了的i行,其状态为s,的方案数. 两个状态之间是否可以转移就留给读者自己思考了. 答案就是\(f_{n,0}\)因为最后一行对下一行不能造成影响. 然而,这样只有60分. 100分是个矩阵快速幂, B矩阵构造很简单,当两个状态\(s.s'\)可以转移,那么,B矩阵\(g_{s,s'}=1\). 当i等于零时, A矩阵为{1, 0 \(<\)repeats 15

【GDOI2020模拟01.16】划愤(nim积+行列式)

https://gmoj.net/senior/#contest/show/2989/1 先考虑n=2时怎么做,打表找规律找了半天找不出来. 赛后才知道这是nim积. 定义\(x?y\)为\(sg(x,y)\). 有一坨性质: \(x,y<2^{2^k},x?y<2^{2^k}\) \(2^{2^k}?2^{2^k}={3 \over 2}2^{2^k}\) 可以把?看做乘法,\(⊕\)(异或)看做加法,所以还有分配律. 求\(x?y(x>y)\),设\(k\)为最大的\(k\)满足\(

【GDOI2020模拟01.16】树上的鼠 (博弈+长链剖分优化dp)

https://gmoj.net/senior/#contest/show/2989/2 思考什么时候先手会赢. 一开始双方都不会希望走到直径的端点上,因为那样对方就可以走直径而使自己输掉. 删掉直径的端点,考虑剩下的树的子问题. 如果又走到端点去了,对面就走到另外一个端点,那我就走到下一层的直径端点去了. 所以大家一直都不想走到直径端点. 一直删,如果最后只剩1一个点,说明先手必败,否则先手必胜. 如果是一条链,就是链的两边的长度不等先手就必胜. 如果是一棵树,考虑随便找一条直径,每次删去它的

6445. 【GDOI2020模拟01.19】String

题目 正解 一听到正解是NTT,我心态崩了. 我特么知道是NTT都不知道该怎么做!哪里像个卷积了? 好吧,是我孤陋寡闻-- 设两个字符串分别为\(A\)和\(B\) 可以考虑试着计算出\(A\)每个子串和\(B\)的相似度(就是位置相同.字母相同的个数),直接统计就完事了. 看到字符集这么小,就可以对于每个字母分开考虑. 假如\(A_i=B_j\),那么以\(A_{i-j+1}\)开头的子串就有\(1\)的贡献. 这样一来,看起来就很像是个卷积了. 搞完之后将贡献加起来,统计即可. 总结 还是没

6438. 【GDOI2020模拟01.16】树上的鼠

题目 由于时间过于久远,而且题面本身也很清晰,所以就懒得另外叙述题目大意了(还有思考历程). 正解 先考虑一条链的情况(长度为奇数,这里的长度是指点的数量): 如果根在中点,先手无论移到哪里,后手都可以移到它的对称点去. 此时先手必败: 如果根不在中点,先手只要一开始移到中点,先手就赢了. 若长度为偶数,就将中间的两个点都看成中点. 先手第一步先移到离根比较远的那个中点上,以后就用一样的策略,每次到达对方的对称点.所以偶数时先手必胜. 然后这就可以推广到一棵树的情况. 可以发现先手必败的情况当且