【LOJ】#2277. 「HAOI2017」方案数
题解
这个出题人完美诠释了什么叫
用心出题,用脚造数据
算完复杂度怎么也得\(O(o^2 * 200)\)略微跑不满,但是有8个测试点虽然有障碍但是一个障碍都不在路径上,2个测试点只有10来个点在路径上
这么轻松愉快的嘛????
如果没有障碍的话只和\(1\)的数量有关
那么我们设\(dp[i][j][k]\)表示第一维有\(i\)个\(1\)第二维有\(j\)个\(1\)第三维有\(k\)个\(1\)的方案数
转移的时候枚举哪一位增加了多少1
方案数是
\(\binom{i}{h}\cdot dp[i - h][j][k] \rightarrow dp[i][j][k]\)
\(\binom{j}{h}\cdot dp[i][j - h][k] \rightarrow dp[i][j][k]\)
\(\binom{k}{h}\cdot dp[i][j][k - h] \rightarrow dp[i][j][k]\)
然后就成功得到80分做完预处理了
然后我没啥好想法了我觉得就设一个\(f[i][j]\)表示走到第\(i\)个点至少经过\(j\)个点
估算一下第二维最多是60 +60 + 60
然后我按照每个点的第一维排序,第一维相等按第二维,第二维相等按第三维,这就是拓扑序了,就暴力更新一下就好了吧(因为感觉跑满复杂度的点不太好造)
结果这不满的也太厉害了吧= =,实际上o<=20了解一下????
update:翻了stdcall的代码发现根本用不上第二维,因为每次转移的时候多了一个点相当于取反一次,所以就是\(O(o^2)\)的
我好菜啊QAQ
代码
#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define pdi pair<db,int>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define eps 1e-8
#define MAXN 100005
#define mo 974711
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
const int MOD = 998244353;
int64 N,M,R,x[10005],y[10005],z[10005];
int dp[64][64][64],C[64][64],ans;
bool vis[10005];
int f[10005],O,cntx[10005],cnty[10005],cntz[10005],id[10005],idx,cn,cm,cr;
int64 lowbit(int64 x) {return x & (-x);}
int inc(int a,int b) {
return a + b >= MOD ? a + b - MOD : a + b;
}
int mul(int a,int b) {
return 1LL * a * b % MOD;
}
int calc(int64 x) {
int cnt = 0;
while(x) {
++cnt;
x -= lowbit(x);
}
return cnt;
}
bool cmp(int a,int b) {
if(x[a] != x[b]) return x[a] < x[b];
if(y[a] != y[b]) return y[a] < y[b];
return z[a] < z[b];
}
void Solve() {
read(N);read(M);read(R);
C[0][0] = 1;
for(int i = 1 ; i <= 62 ; ++i) {
C[i][0] = 1;
for(int j = 1 ; j <= i ; ++j) {
C[i][j] = inc(C[i - 1][j - 1],C[i - 1][j]);
}
}
dp[0][0][0] = 1;
for(int i = 0 ; i <= 62 ; ++i) {
for(int j = 0 ; j <= 62 ; ++j) {
for(int k = 0 ; k <= 62 ; ++k) {
if(!(i + j + k)) continue;
for(int h = 1 ; h <= i ; ++h) dp[i][j][k] = inc(dp[i][j][k],mul(dp[i - h][j][k],C[i][h]));
for(int h = 1 ; h <= j ; ++h) dp[i][j][k] = inc(dp[i][j][k],mul(dp[i][j - h][k],C[j][h]));
for(int h = 1 ; h <= k ; ++h) dp[i][j][k] = inc(dp[i][j][k],mul(dp[i][j][k - h],C[k][h]));
}
}
}
ans = dp[cn = calc(N)][cm = calc(M)][cr = calc(R)];
read(O);
for(int i = 1 ; i <= O ; ++i) {
read(x[i]);read(y[i]);read(z[i]);
cntx[i] = calc(x[i]);cnty[i] = calc(y[i]);cntz[i] = calc(z[i]);
if((x[i] & N) == x[i] && (y[i] & M) == y[i] && (z[i] & R) == z[i]) id[++idx] = i;
}
sort(id + 1,id + idx + 1,cmp);
for(int i = 1 ; i <= idx ; ++i) {
int u = id[i];
f[u] = inc(f[u],MOD - dp[cntx[u]][cnty[u]][cntz[u]]);
ans = inc(ans,mul(f[u],dp[cn - cntx[u]][cm - cnty[u]][cr - cntz[u]]));
for(int k = i + 1 ; k <= idx ; ++k) {
if((x[u] & x[id[k]]) == x[u] && (y[u] & y[id[k]]) == y[u] && (z[u] & z[id[k]]) == z[u]) {
f[id[k]] = inc(f[id[k]],mul(f[u],MOD - dp[cntx[id[k]] - cntx[u]][cnty[id[k]] - cnty[u]][cntz[id[k]] - cntz[u]]));
}
}
}
out(ans);enter;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
}
【LOJ】#2277. 「HAOI2017」方案数的更多相关文章
- LOJ 3094 「BJOI2019」删数——角标偏移的线段树
题目:https://loj.ac/problem/3094 弱化版是 AGC017C . 用线段树维护那个题里的序列即可. 对应关系大概是: 真实值的范围是 [ 1-m , n+m ] :考虑设偏移 ...
- @loj - 2174@ 「FJOI2016」神秘数
目录 @description@ @solution@ @accepted code@ @details@ @description@ 一个可重复数字集合 S 的神秘数定义为最小的不能被 S 的子集的 ...
- loj#2312. 「HAOI2017」八纵八横(线性基 线段树分治)
题意 题目链接 Sol 线性基+线段树分治板子题.. 调起来有点自闭.. #include<bits/stdc++.h> #define fi first #define se secon ...
- 【LOJ】#3094. 「BJOI2019」删数
LOJ#3094. 「BJOI2019」删数 之前做atcoder做到过这个结论结果我忘了... em,就是\([1,n]\)之间每个数\(i\),然后\([i - cnt[i] + 1,i]\)可以 ...
- Loj #3056. 「HNOI2019」多边形
Loj #3056. 「HNOI2019」多边形 小 R 与小 W 在玩游戏. 他们有一个边数为 \(n\) 的凸多边形,其顶点沿逆时针方向标号依次为 \(1,2,3, \ldots , n\).最开 ...
- Loj 3058. 「HNOI2019」白兔之舞
Loj 3058. 「HNOI2019」白兔之舞 题目描述 有一张顶点数为 \((L+1)\times n\) 的有向图.这张图的每个顶点由一个二元组 \((u,v)\) 表示 \((0\le u\l ...
- Loj #2554. 「CTSC2018」青蕈领主
Loj #2554. 「CTSC2018」青蕈领主 题目描述 "也许,我的生命也已经如同风中残烛了吧."小绿如是说. 小绿同学因为微积分这门课,对"连续"这一概 ...
- Loj #2719. 「NOI2018」冒泡排序
Loj #2719. 「NOI2018」冒泡排序 题目描述 最近,小 S 对冒泡排序产生了浓厚的兴趣.为了问题简单,小 S 只研究对 *\(1\) 到 \(n\) 的排列*的冒泡排序. 下面是对冒泡排 ...
- Loj #3102. 「JSOI2019」神经网络
Loj #3102. 「JSOI2019」神经网络 题目背景 火星探险队发现,火星人的思维方式与人类非常不同,是因为他们拥有与人类很不一样的神经网络结构.为了更好地理解火星人的行为模式,JYY 对小镇 ...
随机推荐
- MT【177】三个乘积和
对任意 2 个 1,2,3,4,5,6 的全排列 $(a_1,a_2,a_3,a_4,a_5,a_6)$ 和 $(b_1,b_2,b_3,b_4,b_5,b_6)$,求$\displaystyle S ...
- EasyUI实战篇之datagrid:如何重新设置datagrid所配置的属性(options)并重新查询列表(relaod)
http://www.stepday.com/topic/?873 今天在使用EasyUI的datagrid列表组件想实现一个列表的展现,且列表上方有搜索条件,初始化的时候我是这样配置的: 1.< ...
- kubernetes配置secret拉取私仓镜像
2017.05.10 19:48* 字数 390 阅读 5216评论 0喜欢 8 对于公司内部的项目, 我们不可能使用公有开放的镜像仓库, 一般情况可能会花钱买docker私仓服务, 或者说自己在服务 ...
- Go 语言编程规范
1. gofmt 命令 大部分的格式问题可以通过 gofmt 来解决,gofmt 自动格式化代码,保证所有的 go 代码与官方推荐的格式保持一致,所有格式有关问题,都以gofmt的结果为准.所以,建议 ...
- Codeforces 923 C. Perfect Security
http://codeforces.com/contest/923/problem/C Trie树 #include<cstdio> #include<iostream> us ...
- jQuery总结或者锋利的jQuery笔记二
第三章 jQuery 中 DOM 操作 , 进入这一章,你必须先要有 选择器的基础, 最好是基本选择器 (id,class,*,div,p 组合等) , 层次选择器(div ul),(div> ...
- js 正则学习小记之匹配字符串字面量优化篇
昨天在<js 正则学习小记之匹配字符串字面量>谈到 个字符,除了第一个 个,只有 个转义( 个字符),所以 次,只有 次成功.这 次匹配失败,需要回溯后用 [^"] 才能匹配成功 ...
- XHR工厂的实现
ajax这种常见的开发模式已经遍布我们日常的开发之中了,ajax本质还是采用一种轮询的模式,就是隔一段时间去发送一次http请求,获取数据,然后显示在页面之上,当然,ajax比起新兴的WebScoke ...
- javascritpt创建对象
javascript添加对象示例: <script> person=new Object(); person.firstname="Bill"; person.last ...
- bellman-ford算法(判断有没有负环)
#include <iostream> #include <vector> #include<string> #include<cstring> usi ...