I - Union

这是2019女生赛最难的一个题目,但是现在去写,我觉得没有想象之中的那么难。

把这个题目分成几个部分来考虑。

  • 假设给你k个数,让你分成三个集合,满足这四个条件,且不需要考虑时间和空间的复杂度。

    那么这个是不是就是一个8维的 \(dp\)

    dp[i][j][x1][x2][x3][x4][x5][x6] 表示有三个集合i个不同的数,三个集合的数加起来是等于j。
    第一个集合有x1个不同的数,第二个集合有x2个不同的数,第三个集合有x3个不同的数
    第一个和第二个集合并起来有x4个不同的数,第二个和第三个并起来有x5个不同的数
    第一个和第三个集合并起来有x6个不同的数。

    这样其实就是让你划分这k个数到三个集合中满足条件的方案数。

    这个朴素的写法是不是还比较简单而且好写。

  • 但是如果开8个维度都是50这么大肯定是会爆空间而且时间也过不去。

  • 仔细分析发现其实这个可以分成四类,第一类就是等于0,第二类等于1,第三类等于2,第四类大于等于3。

  • \(dp\) 的转移有7种转移方式,而且用刷表法进行转移,则对于一个状态,它转移到的7个状态都互不相同。

  • 所以前三类还是正常转移,对于第四类其实可以一起转移,这是因为大于等于三的每一个状态肯定都要向上转移一次,而且转移到的状态都是一样的,所以这个时候可以同时转移,也只转移了一次,不会出现重复。

//朴素写法
int main(){
init();
int n,k;
scanf("%d%d",&n,&k);
for(int i=1;i<=7;i++) scanf("%d",&a[i]);
dp[0][0][0][0][0][0][0][0]=1;
for(int i=0;i<k;i++)
for(int j=i;j<k;j++)
for(int a=0;a<k;a++)
for(int b=0;b<k;b++)
for(int c=0;c<k;c++)
for(int d=0;d<k;d++)
for(int e=0;e<k;e++)
for(int f=0;f<k;f++){
if(j!=a+b+c) continue;
ll cur=dp[i][j][a][b][c][d][e][f];
dp[i+1][j+1][3,a+1][b][c][3,d+1][e][3,f+1]+=cur;
dp[i+1][j+1][a][b+1][c][d+1][e+1][f]+=cur;
dp[i+1][j+1][a][b][c+1][d][e+1][f+1]+=cur;
dp[i+1][j+2][a+1][b+1][c][d+1][e+1][f+1]+=cur;
dp[i+1][j+2][a][b+1][c+1][d+1][e+1][f+1]+=cur;
dp[i+1][j+2][a+1][b][c+1][d+1][e+1][f+1]+=cur;
dp[i+1][j+3][a+1][b+1][c+1][d+1][e+1][f+1]+=cur;
}
ll ans=0;
for(int i=a[7];i<=k;i++)
for(int x=a[1];x<=k;x++)
for(int y=a[2];y<=k;y++)
for(int z=a[3];z<=k;z++)
for(int b=a[4];b<=k;b++)
for(int c=a[5];c<=k;c++)
for(int d=a[6];d<=k;d++){
if(x+y+z!=k) continue;
ll cur=dp[i][k][x][y][z][b][c][d];
// if(cur) printf("i=%d x=%d y=%d z=%d b=%d c=%d d=%d %lld\n",i,x,y,z,b,c,d,cur);
ans=(ans+dp[i][k][x][y][z][b][c][d]*C[n][i]);
}
printf("%lld\n",ans);
}

优化之后的方法

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
const int mod=1e9+7;
typedef long long ll;
ll dp[55][55][4][4][4][4][4][4];
/*
dp[i][j][x1][x2][x3][x4][x5][x6] 表示有三个集合i个不同的数,三个集合的数加起来是等于j。
第一个集合有x1个不同的数,第二个集合有x2个不同的数,第三个集合有x3个不同的数
第一个和第二个集合并起来有x4个不同的数,第二个和第三个并起来有x5个不同的数
第一个和第三个集合并起来有x6个不同的数。
所以对于新增加一个数,那么它可能在 A,B,C,AB,AC,BC,ABC
dp[i+1][j+1][x1+1][x2][x3][x4+1][x5+1][x6]+=1 现在重新对dp进行定义
dp[i][j][x1][x2][x3][x4][x5][x6]
表示有i个不同的数字,三个集合的和是j */
ll C[maxn][55];
ll init(){
for(int i=0;i<maxn;i++){
C[i][0]=1;
for(int j=1;j<=min(i,50);j++){
C[i][j]=C[i-1][j]+C[i-1][j-1];
}
}
}
int a[10];
int main(){
init();
int n,k;
scanf("%d%d",&n,&k);
for(int i=1;i<=7;i++) scanf("%d",&a[i]);
dp[0][0][0][0][0][0][0][0]=1;
for(int i=0;i<k;i++)
for(int j=i;j<k;j++)
for(int a=0;a<=3;a++)
for(int b=0;b<=3;b++)
for(int c=0;c<=3;c++)
for(int d=0;d<=3;d++)
for(int e=0;e<=3;e++)
for(int f=0;f<=3;f++){
ll cur=dp[i][j][a][b][c][d][e][f];
dp[i+1][j+1][min(a+1,3)][b][c][min(d+1,3)][e][min(f+1,3)]+=cur;
dp[i+1][j+1][a][min(b+1,3)][c][min(d+1,3)][min(3,e+1)][f]+=cur;
dp[i+1][j+1][a][b][min(3,c+1)][d][min(3,e+1)][min(3,f+1)]+=cur;
dp[i+1][j+2][min(3,a+1)][min(3,b+1)][c][min(3,d+1)][min(3,e+1)][min(3,f+1)]+=cur;
dp[i+1][j+2][a][min(3,b+1)][min(3,c+1)][min(3,d+1)][min(3,e+1)][min(3,f+1)]+=cur;
dp[i+1][j+2][min(3,a+1)][b][min(3,c+1)][min(3,d+1)][min(3,e+1)][min(3,f+1)]+=cur;
dp[i+1][j+3][min(3,a+1)][min(3,b+1)][min(3,c+1)][min(3,d+1)][min(3,e+1)][min(3,f+1)]+=cur;
}
ll ans=0;
for(int i=a[7];i<=k;i++)
for(int x=a[1];x<=3;x++)
for(int y=a[2];y<=3;y++)
for(int z=a[3];z<=3;z++)
for(int b=a[4];b<=3;b++)
for(int c=a[5];c<=3;c++)
for(int d=a[6];d<=3;d++){
ans=(ans+dp[i][k][x][y][z][b][c][d]*C[n][i])%mod;
}
printf("%lld\n",ans);
}

I - Union 2019ccpc女生赛的更多相关文章

  1. 2019.ccpc女生赛-wfinal总结

    2019ccpc女生赛离它结束有四天了,在这个期间我想了很多,想了想还是决定写这个总结.作为这个队伍唯一的一名大一队员,我很庆幸,能跟着两个学姐一起打比赛,计爱玲师姐,即将工作,张莹俐学姐.这估计都是 ...

  2. 2016女生赛 HDU 5710 Digit-Sum(数学,思维题)

    Digit-Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total S ...

  3. 2019-CCPC广东省赛总结

    2018年11月第一次参加ICPC区域赛青岛赛区,打铁了! 2019年5月第一次参加CCPC广东省赛,4题滚粗,C题莫队TLE13发,只拿了个铜牌! 教训总结: 比赛时千万不能犹豫,不能犹豫,不能犹豫 ...

  4. [2019CCPC网络赛][hdu6704]K-th occurrence(后缀数组&&主席树)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6704 题意为查询子串s[l...r]第k次出现的位置. 写完博客后5分钟的更新 写完博客才发现这份代码 ...

  5. 记第二届CCPC全国女生赛参赛体验

    离比赛时间已经有点久了,今天整理博客看到“”参赛体会“”这一分类,觉得记录一下也好 流水账记一下感受 因为题目我已经忘记了.. 第一次..那么久..大概有三个多小时在金牌区吧.. 然后就是一无所出了. ...

  6. 2018CCPC女生赛(树上莫队)

    签到题这里久懒得写了. B - 缺失的数据范围 Total Submission(s): 2602    Accepted Submission(s): 559 题意:求最大的N,满足N^a*[log ...

  7. 2018 CCPC 女生赛 hdoj6287 口算训练

    题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=6287 Summarize: 1.分解质因数: 2.二分查找函数lower_bound与upper_bo ...

  8. 2018 CCPC 女生赛 hdoj6288 缺失的数据范围

    题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=6288 Summarize:1.二分查找答案: 2.自带log函数精度不够,需自己写: 3.注意二分递归 ...

  9. 2019CCPC网络赛 C - K-th occurrence HDU - 6704(后缀数组+ST表+二分+主席树)

    题意 求区间l,r的子串在原串中第k次出现的位置. 链接:https://vjudge.net/contest/322094#problem/C 思路 比赛的时候用后缀自动机写的,TLE到比赛结束. ...

随机推荐

  1. 创建 SysV 风格的 linux daemon 程序

    本文介绍如何使用 C 语言创建 Linux 系统中 SysV 风格的 daemon 程序.注意:这是一种旧式的 daemon 程序写法,进入 systemd 时代后是不需要通过这样的方式创建 daem ...

  2. http的长连接和websocket的区别

    一.什么是http协议 HTTP是一个应用层协议,无状态的,端口号为80.主要的版本有1.0/1.1/2.0.   HTTP/1.* 一次请求-响应,建立一个连接,用完关闭: HTTP/1.1 串行化 ...

  3. skynet启动流程及调用服务

     3.基本原理 3.1启动流程  1.skynet-src/skynet_main.c 这个是main()函数所在,主要就是设置一下lua的环境.默认的配置.打开config配置文件,并修改默认配置. ...

  4. 从零开始学AB测试:基础篇

    什么是AB测试? 通俗点理解,AB测试就是比较两个东西好坏的一套方法,这种A和B的比较在我们的生活和人生中非常常见,所以不难理解.具体到AB测试这个概念,它和我们比较哪个梨更大.比较哪个美女更漂亮.比 ...

  5. python里的内置函数你知道有多少个吗?

    Python 内置函数最全汇总: 1 abs() 绝对值或复数的模 2 all() 接受一个迭代器,如果迭代器的所有元素都为真,那么返回True,否则返回False 3 any() 接受一个迭代器,如 ...

  6. 数值计算方法实验之newton多项式插值 (Python 代码)

    一.实验目的 在己知f(x),x∈[a,b]的表达式,但函数值不便计算或不知f(x),x∈[a,b]而又需要给出其在[a,b]上的值时,按插值原则f(xi)=yi (i=0,1,……, n)求出简单函 ...

  7. pytorch torchversion自带的数据集

    from torchvision.datasets import MNIST # import torchvision # torchvision.datasets. #准备数据集 mnist = M ...

  8. [Inno Setup] How to create a OuterNotebook/welcome page in the uninstaller

    By Martin Prikryl https://stackoverflow.com/questions/42625626/inno-setup-how-to-create-a-outernoteb ...

  9. js 实现淘宝无缝轮播图效果,可更改配置参数 带完整版解析代码[slider.js]

    前言:         本人纯小白一个,有很多地方理解的没有各位大牛那么透彻,如有错误,请各位大牛指出斧正!小弟感激不尽.         本篇文章为您分析一下原生JS写淘宝无缝轮播图效果 需求分析: ...

  10. socket编程-多个客户端向服务器发送人脸照片,服务器返回识别结果(服务器使用多线程)...

    recognition.py import numpy as np import face_recognition import os class recognition: def __init__( ...