【题解】CF#236(Div. 1) D-Beautiful Pairs of Numbers

 这题还挺对胃口的哈哈~是喜欢的画风!回家路上一边听歌一边想到的解法,写出来记录一下……

 首先,由于 \(b_{k} < a_{k + 1}\) ,所以我们可以看作是在一个长度为 n 的序列上选择出 k 个不相交的区间使得这 k个区间的长度各不相同。那么我们可以先求出 \(f[i][j]\) 表示选择了 \(i\) 个区间,这 \(i\) 个区间的区间长度总和为 \(j\) 的方案数。然后,我们考虑用这些方案数与序列剩下的长度的划分的方案数共同构成答案。所以我们再求一个 \(g[i][j]\) 表示将 \(j\) 的长度划分成可空的 \(i\) 段的方案数。答案 \(h[k][n]\) 表示在长为 n 的序列上选出了 \(k\) 个不相交,各不相同的区间的方案数。有了 \(f,g\)数组,我们只需要枚举一下选择的区间总长 i,将 \(f[k][i] * g[k + 2][n - i]\) 加到答案中即可。

  但是,这样做不是 \(1000^{3}\) 的的吗?实际上,k 的取值范围远不可能到达 1000。由于区间的长度各不相同,我们不难求出当 \(k >= 45\) 的时候答案为 0,并不需要计算。这样,我们就可以在优秀的 \(5e7\) 的复杂度下通过此题~

#include <bits/stdc++.h>
using namespace std;
#define maxn 1010
#define maxm 100000
#define maxk 50
#define mod 1000000007
#define int long long
int N = 1005, lim = 45, h[maxn][maxn];
int t[2][maxk][maxn], f[maxk][maxn], g[maxk][maxn];
int fac[maxm], inv[maxm];

int read()
{
    int x = 0, k = 1;
    char c; c = getchar();
    while(c < ‘0‘ || c > ‘9‘) { if(c == ‘-‘) k = -1; c = getchar(); }
    while(c >= ‘0‘ && c <= ‘9‘) x = x * 10 + c - ‘0‘, c = getchar();
    return x * k;
}

int C(int n, int m)
{
    if(n < m || n < 0 || m < 0) return 0;
    return fac[n] * inv[m] % mod * inv[n - m] % mod;
}

void pre()
{
    fac[0] = 1; inv[0] = inv[1] = 1;
    for(int i = 1; i < maxm; i ++) fac[i] = fac[i - 1] * i % mod;
    for(int i = 2; i < maxm; i ++) inv[i] = (mod - mod / i) * inv[mod % i] % mod;
    for(int i = 2; i < maxm; i ++) inv[i] = inv[i - 1] * inv[i] % mod;
}

void Up(int &x, int y) { x = x + y; if(x >= mod) x -= mod; }
void Work()
{
    int pre = 0, now = 1; t[pre][0][0] = 1;
    for(int i = 1; i <= N; i ++)
    {
        memset(t[now], 0, sizeof(t[now]));
        for(int k = 0; k <= lim; k ++)
            for(int j = 0; j <= N; j ++)
            {
                t[now][k][j] = t[pre][k][j];
                if(k && j - i >= 0) Up(t[now][k][j], t[pre][k - 1][j - i]);
            }
        swap(pre, now);
    }
    for(int i = 1; i <= lim; i ++)
        for(int j = 1; j <= N; j ++)
            f[i][j] = t[pre][i][j] * fac[i] % mod;
    for(int i = 0; i <= lim; i ++) g[i][0] = 1;
    for(int i = 1; i <= lim; i ++)
        for(int j = 1; j <= N; j ++)
            g[i][j] = C(i + j - 1, j);

    for(int i = 1; i <= lim; i ++)
        for(int j = 1; j < N; j ++)
        {
            int ret = 0;
            for(int k = 1; k <= j; k ++)
                Up(ret, f[i][k] * g[i + 1][j - k] % mod);
            h[i][j] = ret;
        }
}

signed main()
{
    pre(); Work(); int T = read();
    while(T --)
    {
        int n = read(), K = read();
        if(K <= lim) printf("%I64d\n", h[K][n]);
        else printf("0\n");
    }
    return 0;
}

原文地址:https://www.cnblogs.com/twilight-sx/p/9868276.html

时间: 2024-12-18 00:27:40

【题解】CF#236(Div. 1) D-Beautiful Pairs of Numbers的相关文章

[CF #236 (Div. 2) E] Strictly Positive Matrix(强联通分量)

题目:http://codeforces.com/contest/402/problem/E 题意:给你一个矩阵a,判断是否存在k,使得a^k这个矩阵全部元素都大于0 分析:把矩阵当作01矩阵,超过1的都当作1,那么a矩阵可表示一个有向图的走一次的连通性,则a^k表示有向图走K次的连通性.既然要求最后都没0,即走了K次后,每个点都能互通,这也说明这个图必然是只有一个强联通分量.于是判断k的存在有无,也就是判断a矩阵表示的有向图是不是只有一个强联通分量.

[CF403D]Beautiful Pairs of Numbers

题意:给定$n,k$,对于整数对序列$\left(a_1,b_1\right),\cdots,\left(a_k,b_k\right)$,如果$1\leq a_1\leq b_1\lt a_2\leq b_2\lt\cdots\lt a_k\leq b_k\leq n$且所有的$b_i-a_i$互不相同,则称这个序列是“美丽的”,求美丽的序列的个数 先转化一下,把每个数对$\left(a_i,b_i\right)$看作一个区间$\left[a_i,b_i\right]$,则题目要求的是$k$个长

CF#247(Div. 2)部分题解

引言: 在软件项目中,Maven提供了一体化的类库管理系统,非常实用.但是,如果新增的类库jar在网络上无法获取到,如何在本地按照Maven的规则添加进来呢?本文将通过一个小例子展示新增过程. 背景介绍: 一个Maven管理的Java项目,提供一个系统级别的POM.xml,其中定义了整个项目使用的类库. 需求: 需要添加一个自定义的类库到当前项目中.假定当前的类库文件名为:abc.jar.. 如何将类库添加进来? 1.  找到当前Maven的Repository类库位置 一般默认情况下,在win

【题解】CF#474(Div.1+Div.2) H-Santa&#39;s Gift

好久没有写过数据结构题目了,果然还是太不自信.实际上就是要求统计一个式子: \(\sum (c[k]*p[k] - C)^{2}\) 拆开,分别统计和与平方和 \(co[k] * \sum p[k]^{2} - 2 * C * co[k] \sum p[k] + \sum C ^{2}\) 显然可以用树链剖分 + 线段树维护 平方和在区间 + 1的时候直接用 \((x + 1) ^ {2} = x^2 + 2 * x + 1\) 计算即可. 至于不同的口味的问题,我们给每个口味都开一线段树,动态

CF #371 (Div. 2) C、map标记

1.CF #371 (Div. 2)   C. Sonya and Queries  map应用,也可用trie 2.总结:一开始直接用数组遍历,果断T了一发 题意:t个数,奇变1,偶变0,然后与问的匹配. #include<bits/stdc++.h> #define max(a,b) a>b?a:b #define F(i,a,b) for (int i=a;i<=b;i++) #define mes(a,b) memset(a,b,sizeof(a)) #define INF

CF #375 (Div. 2) D. bfs

1.CF #375 (Div. 2)  D. Lakes in Berland 2.总结:麻烦的bfs,但其实很水.. 3.题意:n*m的陆地与水泽,水泽在边界表示连通海洋.最后要剩k个湖,总要填掉多少个湖,然后输出. #include<bits/stdc++.h> #define F(i,a,b) for (int i=a;i<b;i++) #define FF(i,a,b) for (int i=a;i<=b;i++) #define mes(a,b) memset(a,b,s

CF #374 (Div. 2) D. 贪心,优先队列或set

1.CF #374 (Div. 2)   D. Maxim and Array 2.总结:按绝对值最小贪心下去即可 3.题意:对n个数进行+x或-x的k次操作,要使操作之后的n个数乘积最小. (1)优先队列 #include<bits/stdc++.h> #define F(i,a,b) for (int i=a;i<b;i++) #define FF(i,a,b) for (int i=a;i<=b;i++) #define mes(a,b) memset(a,b,sizeof(

cf #254 (Div. 2)

a题 #include<stdio.h> #include<string.h> char c[101][101]; int main() { long n,m,i,j; scanf("%ld%ld",&n,&m); gets(c[0]); for(i=1;i<=n;i++) gets(c[i]); for(i=1;i<=n;i++) { for(j=0;j<m;j++) if(c[i][j]=='-') printf("

B. Mr. Kitayuta&#39;s Colorful Graph (CF #286 (Div. 2) 并查集)

B. Mr. Kitayuta's Colorful Graph time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Mr. Kitayuta has just bought an undirected graph consisting of n vertices and m edges. The vertices of the g