LOJ#3109. 「TJOI2019」甲苯先生的线段树

发现如果枚举路径两边的长度的话,如果根节点的值是\(x\),左边走了\(l\),右边走了\(r\)

肯定答案会是\((2^{l + 1} + 2^{r + 1} - 3)x + t\),可以发现\(t < (2^{l + 1} + 2^{r + 1} - 3)\),于是考虑计算对于\(t\),左边走了\(l\),右边走了深度\(r\),几种走法使得总和为\(t\)

容易发现右边最小一定是走了\(2^{r} - 1\)于是可以扣掉

再发现我们其实是对于左边和右边串选择长度为\([1,l - 1]\)和\([1,r - 1]\)的11111111......

但是这种\(i\)个1的形式不太好dp,于是就转化成\(2^{i + 1} - 1\)的形式,每次强制选择的个数,只要考虑\(2^{i+ 1}\)去dp就好了,\(t\)加上强制选的个数再进行数位dp就可以了

复杂度是\(d^{5}\)的,有点慢,但是可以过,因为上界很远。。。

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define space putchar(' ')
#define enter putchar('\n')
#define eps 1e-10
#define MAXN 200005
#define ba 47
//#define ivorysi
using namespace std;
typedef long long int64;
typedef unsigned int u32;
typedef double db;
template<class T>
void read(T &res) {
res = 0;T f = 1;char c = getchar();
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);
}
int d,c;int64 a,b,s;
int getpos(int64 x) {
int res = 0;
while(x) {
++res;
x >>= 1;
}
return res;
}
int64 GetSum(int64 a,int64 b) {
int ta = getpos(a),tb = getpos(b);
if(ta > tb) {swap(a,b);swap(ta,tb);}
int64 res = 0;
for(int i = 1 ; i <= tb - ta ; ++i) {res += b;b >>= 1;}
while(a != b) {
res += a;res += b;
a >>= 1;b >>= 1;
}
res += a;
return res;
}
map<int64,int64> zz;
int La,Lb;
int64 dp[55][105][2];
int64 Process(int64 s,int num) {
memset(dp,0,sizeof(dp));
dp[0][0][0] = 1;
if(s & 1) return 0;
for(int i = 1 ; i <= 50 ; ++i) {
int to = (s >> i) & 1;
for(int j = 0 ; j <= num ; ++j) {
for(int t = 0 ; t <= 1 ; ++t) {
int up = (i <= La) + (i <= Lb);
for(int h = 0 ; h <= up ; ++h) {
if(((t + h) & 1) == to) {
int64 f = 1;
if(h == 1 && up == 2) f = 2;
dp[i][j + h][(t + h - to) / 2] += f * dp[i - 1][j][t];
}
}
}
}
}
return dp[50][num][0];
}
int64 Calc() {
int64 res = 0;
for(int i = 0 ; i <= d ; ++i) {
for(int j = 0 ; j <= d ; ++j) {
int64 k = (1LL << i + 1) + (1LL << j + 1) - 3;
int64 tmp = s;
if(tmp < k) continue;
if(getpos(tmp / k) + max(i,j) > d) continue;
tmp = tmp % k;
if(tmp < (1LL << j) - 1) continue;
tmp -= (1LL << j) - 1;
if(tmp == 0) {++res;continue;}
La = i - 1,Lb = j - 1;
for(int h = 0 ; h <= max(i - 1,0) + max(j - 1,0) ; ++h) {
res += Process(tmp + h,h);
}
}
}
return res;
}
void Solve() {
read(d);read(a);read(b);read(c);
s = GetSum(a,b);
if(c == 1) {out(s);enter;}
else {out(Calc() - 1);enter;}
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
int T;
read(T);
for(int i = 1 ; i <= T ; ++i) {
Solve();
}
return 0;
}

(权游文化还行。。。最近刚开始追权游23333感觉题面非常有趣)

【LOJ】#3109. 「TJOI2019」甲苯先生的线段树的更多相关文章

  1. LOJ 2302 「NOI2017」整数——压位线段树

    题目:https://loj.ac/problem/2302 压30位,a最多落在两个位置上,拆成两次操作. 该位置加了 a 之后,如果要进位或者借位,查询一下连续一段 0 / 1 ,修改掉,再在含有 ...

  2. LOJ#3104「TJOI2019」甲苯先生的字符串

    题目描述 一天小甲苯得到了一条神的指示,他要把神的指示写下来,但是又不能泄露天机,所以他要用一种方法把神的指示记下来. 神的指示是一个字符串,记为字符串 \(s_1\),\(s_1\) 仅包含小写字母 ...

  3. loj#2312. 「HAOI2017」八纵八横(线性基 线段树分治)

    题意 题目链接 Sol 线性基+线段树分治板子题.. 调起来有点自闭.. #include<bits/stdc++.h> #define fi first #define se secon ...

  4. LG5337/BZOJ5508 「TJOI2019」甲苯先生的字符串 线性动态规划+矩阵加速

    问题描述 LG5337 BZOJ5508 题解 设\(opt_{i,j}(i \in [1,n],j \in [1,26])\)代表区间\([1,i]\),结尾为\(j\)的写法. 设\(exist_ ...

  5. LG5338/BZOJ5509/LOJ3105 「TJOI2019」甲苯先生的滚榜 Treap

    问题描述 LG5338 LOJ3105 BZOJ5509 题解 建立一棵\(\mathrm{Treap}\),把原来的\(val\)换成两个值\(ac,tim\) 原来的比较\(val_a<va ...

  6. 「TJOI2019」甲苯先生的滚榜

    题目链接 问题分析 参照数据范围,我们需要一个能够在\(O(n\log n)\)复杂度内维护有序数列的数据结构.那么平衡树是很好的选择.参考程序中使用带旋Treap. 参考程序 #pragma GCC ...

  7. LOJ 3055 「HNOI2019」JOJO—— kmp自动机+主席树

    题目:https://loj.ac/problem/3055 先写了暴力.本来想的是 n<=300 的那个在树上暴力维护好整个字符串, x=1 的那个用主席树维护好字符串和 nxt 数组.但 x ...

  8. LOJ 2339 「WC2018」通道——边分治+虚树

    题目:https://loj.ac/problem/2339 两棵树的话,可以用 CTSC2018 暴力写挂的方法,边分治+虚树.O(nlogn). 考虑怎么在这个方法上再加一棵树.发现很难弄. 看了 ...

  9. 2018.06.26「TJOI2018」数学计算(线段树)

    描述 小豆现在有一个数 xxx ,初始值为 111 . 小豆有 QQQ 次操作,操作有两种类型: 111 $ m$ : x=x×mx=x×mx=x×m ,输出 xxx modmodmod MMM : ...

随机推荐

  1. POJ - 3376 Finding Palindromes manacher+字典树

    题意 给n个字符串,两两拼接,问拼接后的\(n\times n\)个字符串中有多少个回文串. 分析 将所有正串插入字典树中,马拉车跑出所有串哪些前缀和后缀为回文串,记录位置,用反串去字典树中查询,两字 ...

  2. WM_PAINT(父子窗口间)

    WM_PAINT(父子窗口间) 窗口句柄(HWND)都是由操作系统内核管理的,系统内部有一个z-order序列,记录着当前从屏幕底部(假象的从屏幕到眼睛的方向),到屏幕最高层的一个窗口句柄的排序,这个 ...

  3. tomcat使用实践三种运行模式之apr

    tomcat有三种运行模式 nio,bio,apr bio是阻塞式IO操作,使用的是传统的java i/o处理方式,对于每一个请求都要创建一个线程来进行处理,所以开销较大不适合处理高并发的场景 nio ...

  4. 第二章 Python数据导入

    数据导入 数据存储的两个地方: 文件 CSV.Excel.TXT(学习层面) 数据库(公司实战层面) Mysql.Access.SQL Server 导入CSV文件 CSV文件第一行是列名,第二行到最 ...

  5. Codeforces 678E. Another Sith Tournament(概率DP,状压)

    Codeforces 678E. Another Sith Tournament 题意: n(n<=18)个人打擂台赛,给定任意两人对决的胜负概率,比赛规则:可指定一人作为最开始的擂主,每次可指 ...

  6. python合并两个字典

    1.借助dict(d1.items() + d2.items())的方法 2.借助字典的update()方法,没有返回值 3.借助字典的dict(d1, **d2)方法 4.d3={**d1,**d2 ...

  7. IntelliJ IDEA 2017.3 创建多Module项目时,右边栏出现多个root模块的问题。如图。

    我新建了一个项目,里面有三个模块(Module),结果建好后,出现了三个root.然后我发现主模块的pom文件,包含这样一段配置 <modules> <module>desig ...

  8. LeetCode205----同构字符串

    给定两个字符串 s 和 t,判断它们是否是同构的. 如果 s 中的字符可以被替换得到 t ,那么这两个字符串是同构的. 所有出现的字符都必须用另一个字符替换,同时保留字符的顺序.两个字符不能映射到同一 ...

  9. 1.2 Go语言基础之变量和常量

    变量和常量是编程中必不可少的部分,也是很好理解的一部分. 一.标识符与关键字 1.1 标识符 在编程语言中标识符就是程序员定义的具有特殊意义的词,比如变量名.常量名.函数名等等. Go语言中标识符由字 ...

  10. [mybatis]传值和返回结果

    一.传值:parameterType的形式:可以传递一个类,也可以是一个map <update id="updateCategory" parameterType=" ...