题目描述

LYK喜欢兔子,它在家中养了3只兔子。

有一天,兔子不堪寂寞玩起了游戏,3只兔子排成一排,分别站在a,b,c这3个位置。

游戏的规则是这样的,重复以下步骤k次:选择两个不同的兔子A和B,假如它们位于X与Y,A可以从X跳到Y+Y-X处,但是跳跃时是不允许一下子跳过两只兔子的,也就是说第三只兔子不在[min{X,Y+Y-X},max{X,Y+Y-X}]处。

现在3只小兔子的位置分别到了x,y,z(3只兔子长得一样,即三只兔子跳完之后的顺序可以变化)处,但是它们忘记一开始是怎么跳的了,想让你帮它们还原跳法。但这个问题非常easy,于是LYK要求你输出方案总数。

保证答案有解。

由于答案巨大,你只需输出答案对1e9+7取模后的结果就可以了。

输入格式(rabbits.in)

第一行3个数a,b,c。

第二行3个数x,y,z。

第三行一个数k。

数据保证3只兔子的起始位置a,b,c严格递增且3只兔子最终的位置x,y,z严格递增。

输出格式(rabbits.out)

一行表示方案总数。

输入样例1

0 2 5

0 2 5

2

输出样例1

3

输入样例2

0 2 4

0 2 4

2

输出样例2

2

样例解释

对于样例1:共有3种跳法,第一次跳完后的位置分别是{0,-2,5},{4,2,5},{0,8,5}。

数据范围

对于100%的数据k<=100,|a|,|b|,|c||x|,|y|,|z|<=10^18。

分析:非常神奇的一道题.

   将3只兔子所在的位置看成一个状态. 那么起点状态S(a,b,c),终点状态T(x,y,z).

   如果中间的兔子往两边跳,那么它能转移到2个新的状态. 如果外面的兔子想往里面跳,那么最多只能有一个兔子往里跳. 这些状态其实构成了一棵二叉树:如果中间的兔子往两边跳,那么就转移到2个儿子节点中,如果两边的兔子往里面跳,就转移到父亲节点中.

   那么现在的问题就变成了:在一棵二叉树中,求节点S到节点T恰好经过k条边的方案数.

   两个点的路径只与它们到LCA之间的路径有关. 令f(i,j,k)表示S与LCA(S,T)之间的距离为i,T与LCA(S,T)之间的距离为j,还能走k条边的方案数. 固定T,只考虑S的移动,分以下几种情况讨论:

   1.如果S已经是LCA了. 如果T也是LCA了. S可以往上走也可以往两个儿子节点走. f(i,j,k) += f(i + 1,j,k - 1) * 2 + f(i,j - 1,k - 1). 乘2是因为有2个儿子节点可以走.  如果T不是LCA. 那么可以走到父亲节点,走到不是T的那个子树和走到T所在的那个子树上. f(i,j,k) += f(i,j + 1,k - 1) + f(i,j - 1,k - 1) + f(i + 1,j,k - 1).

   2.如果S不是LCA. S既可以走到2个儿子节点,也可以走到父亲节点. 转移和上面的类似.

   知道了如何求方案数,该怎么建树呢?

   首先需要明确的是:我们不需要建出整棵树. 因为树的结构就是一棵完全二叉树,每一棵子树的形态结构都是一样的. 根据dp需要的信息,我们只需要求出S和T距离LCA的深度即可.

   先要求出LCA. LCA处的两个状态的兔子的位置全都相同. 让S状态的外面的兔子不断往里跳,T状态的也如此. 最后肯定会有两个状态的兔子的位置完全相等,最早出现的这个状态就是LCA.  为什么要往里跳呢?因为只有这样才能枚举出优先的状态. 否则二叉树就会无限向下扩展.

   小结一下. 做这道题首先要想到把3个兔子的位置看作一个状态. 状态有3种不同的转移方式. 其中有2种的本质是相同的. 联想到二叉树. 求状态A到B的方案数实际上就是求路径数. 树上路径只和这两个点以及它们的LCA有关,由此可以设计出状态. 最后求LCA运用中间相遇法. 思路还是挺巧妙的.

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; typedef long long ll;
const int maxn = ,mod = 1e9+;
ll a[maxn],b[maxn],c[maxn],x[maxn],y[maxn],z[maxn],k,k1,k2,pos1,pos2,f[][][];
bool flag = false; ll dfs(ll X,ll Y,ll K)
{
if (!X && !Y && !K)
return ;
if (X + Y > K)
return ;
if (!X && Y > k2)
return ;
if (f[X][Y][K] != -)
return f[X][Y][K];
if (!X)
{
if (!Y)
f[X][Y][K] = (dfs(X,Y + ,K - ) + dfs(X + ,Y,K - ) * % mod) % mod;
else
f[X][Y][K] = ((dfs(X,Y + ,K - ) + dfs(X,Y - ,K - )) % mod + dfs(X + ,Y,K - )) % mod;
}
else
f[X][Y][K] = (dfs(X + ,Y,K - ) * % mod + dfs(X - ,Y,K - )) % mod;
return f[X][Y][K];
} int main()
{
memset(f,-,sizeof(f));
scanf("%lld%lld%lld%lld%lld%lld%lld",&a[],&b[],&c[],&x[],&y[],&z[],&k);
while (k1 <= k)
{
if (b[k1] - a[k1] == c[k1] - b[k1])
break;
if (b[k1] - a[k1] < c[k1] - b[k1])
{
k1++;
a[k1] = b[k1 - ];
b[k1] = * b[k1 - ] - a[k1 - ];
c[k1] = c[k1 - ];
}
else
{
k1++;
a[k1] = a[k1 - ];
c[k1] = b[k1 - ];
b[k1] = * b[k1 - ] - c[k1 - ];
}
}
while (k2 <= k)
{
if (y[k2] - x[k2] == z[k2] - y[k2])
break;
if (y[k2] - x[k2] < z[k2] - y[k2])
{
k2++;
x[k2] = y[k2 - ];
y[k2] = * y[k2 - ] - x[k2 - ];
z[k2] = z[k2 - ];
}
else
{
k2++;
x[k2] = x[k2 - ];
z[k2] = y[k2 - ];
y[k2] = * y[k2 - ] - z[k2 - ];
}
}
for (pos1 = ; pos1 <= k1 && !flag; pos1++)
for (pos2 = ; pos2 <= k2 && !flag; pos2++)
if (a[pos1] == x[pos2] && b[pos1] == y[pos2] && c[pos1] == z[pos2])
flag = true;
pos1--;
pos2--;
printf("%lld\n",dfs(pos1,pos2,k) % mod); return ;
}

省选模拟赛 LYK loves rabbits(rabbits)的更多相关文章

  1. 省选模拟赛 LYK loves graph(graph)

    题目描述 LYK喜欢花花绿绿的图片,有一天它得到了一张彩色图片,这张图片可以看做是一张n*m的网格图,每个格子都有一种颜色去染着,我们用-1至n*m-1来表示一个格子的颜色.特别地,-1代表这个颜色是 ...

  2. 省选模拟赛 LYK loves string(string)

    题目描述 LYK喜欢字符串,它认为一个长度为n的字符串一定会有n*(n+1)/2个子串,但是这些子串是不一定全部都不同的,也就是说,不相同的子串可能没有那么多个.LYK认为,两个字符串不同当且仅当它们 ...

  3. 【洛谷比赛】[LnOI2019]长脖子鹿省选模拟赛 T1 题解

    今天是[LnOI2019]长脖子鹿省选模拟赛的时间,小编表示考的不怎么样,改了半天也只会改第一题,那也先呈上题解吧. T1:P5248 [LnOI2019SP]快速多项式变换(FPT) 一看这题就很手 ...

  4. @省选模拟赛03/16 - T3@ 超级树

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 一棵 k-超级树(k-SuperTree) 可按如下方法得到:取 ...

  5. 3.28 省选模拟赛 染色 LCT+线段树

    发现和SDOI2017树点涂色差不多 但是当时这道题模拟赛的时候不会写 赛后也没及时订正 所以这场模拟赛的这道题虽然秒想到了LCT和线段树但是最终还是只是打了暴力. 痛定思痛 还是要把这道题给补了. ...

  6. NOI2016模拟赛Zbox loves stack

    #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #i ...

  7. 省选模拟赛第四轮 B——O(n^4)->O(n^3)->O(n^2)

    一 稍微转化一下,就是找所有和原树差距不超过k的不同构树的个数 一个挺trick的想法是: 由于矩阵树定理的行列式的值是把邻接矩阵数值看做边权的图的所有生成树的边权乘积之和 那么如果把不存在于原树中的 ...

  8. NOI2019省选模拟赛 第五场

    爆炸了QAQ 传送门 \(A\) \(Mas\)的童年 这题我怎么感觉好像做过--我记得那个时候还因为没有取\(min\)结果\(100\to 0\)-- 因为是个异或我们肯定得按位考虑贡献了 把\( ...

  9. NOI2019省选模拟赛 第六场

    传送门 又炸了-- \(A\) 唐时月夜 不知道改了什么东西之后就\(A\)掉了\(.jpg\) 首先,题目保证"如果一片子水域曾经被操作过,那么在之后的施法中,这片子水域也一定会被操作&q ...

随机推荐

  1. join 中的on和where的区别

    数据库在通过连接两张或多张表来返回记录时,都会生成一张中间的临时表, 然后再将这张临时表返回给用户. 在使用left jion时,on和where条件的区别如下: 1.on条件是在生成临时表时使用的条 ...

  2. python编辑三级目录

    一.需求分析 三级目录要能够实现以下要求: 显示根目录,任何子目录中都可以通过输入b字符来返回根目录 任何子目录中都可以通过输入q字符来返回上一级目录 主目录进入子目录后,系统能够打印子目录,根据指打 ...

  3. 【ZABBIX】Zabbix触发器的告警原理及创建方法

    概述:       触发器中的表达式使用很灵活,我们可以创建一个复杂的逻辑测试监控,触发器表达式形式如下: {<server>:<key>.<function>(& ...

  4. 华为笔试——C++消重输出

    题目:消重输出 题目介绍: 输入一个正整数,给出消除重复数字以后最大的整数,注意需要考虑长整数. 例: 输入:988274320 输出:9874320 题目分析:这个结果的实现需要两个步骤:消重和排序 ...

  5. Asphalting Roads(翻译!)

    Description City X consists of n vertical and n horizontal infinite roads, forming n × n intersectio ...

  6. Java微笔记(7)

    String 类常用方法 注意点: 字符串 str 中字符的索引从0开始,范围为 0 到 str.length()-1 使用 indexOf 进行字符或字符串查找时,如果匹配返回位置索引:如果没有匹配 ...

  7. Scrum团队成立及《构建之法》第六、七章读后感

    5.Scrum团队成立 5.1 团队名称:喳喳      团队目标:突破渣渣      团队口号:吱吱喳喳      团队照: 5.2 角色分配 产品负责人: 112冯婉莹 Scrum Master: ...

  8. PAT 甲级 1081 Rational Sum (数据不严谨 点名批评)

    https://pintia.cn/problem-sets/994805342720868352/problems/994805386161274880 Given N rational numbe ...

  9. LoadRunner脚本增强技巧之检查点

    检查点的设置理解起来非常简单,就是要在服务器返回的页面中检查是否存在关键信息.检查点函数的错误会导致整个脚本运行结果的失败,通过这个功能可以方便地定位脚本运行中的逻辑错误.检查点的设置通常分为两种,一 ...

  10. USB硬件接口相关

    1.USB 设备端的D+为何要拉一个1.5K电阻到3.3v上?(USB是5v供电,但通信的电平是3.3v,所以上拉电平为3.3v:若要上拉到5v,则上拉电阻为10k) usb有主从设备之分,主设备有: ...