黑红树

问题 B: 黑红树

时间限制: 2 Sec  内存限制: 256 MB
提交: 89  解决: 34

题目描述

Mz们在czy的生日送他一个黑红树种子……czy种下种子,结果种子很快就长得飞快,它的枝干伸入空中看不见了……

Czy发现黑红树具有一些独特的性质。

1、 这是二叉树,除根节点外每个节点都有红与黑之间的一种颜色。

2、 每个节点的两个儿子节点都被染成恰好一个红色一个黑色。

3、 这棵树你是望不到头的(树的深度可以到无限大)

4、 黑红树上的高度这样定义:h(根节点)=0,h[son]=h[father]+1。

Czy想从树根顺着树往上爬。他有p/q的概率到达红色的儿子节点,有1-p/q的概率到达黑色节点。但是他知道如果自己经过的路径是不平衡的,他会马上摔下来。一条红黑树上的链是不平衡的,当且仅当红色节点与黑色节点的个数之差大于1。现在他想知道他刚好在高度为h的地方摔下来的概率的精确值a/b,gcd(a,b)=0。那可能很大,所以他只要知道a,b对K取模的结果就可以了。另外,czy对输入数据加密:第i个询问Qi真正大小将是给定的Q减上一个询问的第一个值a%K.


输入

第一行四个数p,q,T,k,表示走红色节点概率是p/q,以下T组询问,答案对K取模。接下来T行,每行一个数 Q,表示czy想知道刚好在高度Q掉下来的概率(已加密)

输出

输出T行,每行两个整数,表示要求的概率a/b中a%K和b%K的精确值。如果这个概率就是0或1,直接输出0 0或1 1(中间有空格)。

样例输入

样例输入1									样例输入22 3 2 100											2 3 2 201													42													6

样例输出

样例输出1									样例输出20 0													0 15 9	

提示


对于30%数据,p,q<=5,T<=1000,K<=127,对于任意解密后的Q,有Q<=30



对于60%数据,p,q<=20,T<=100000,K<=65535,对于任意解密后的Q,有Q<=1000



对于100%数据,p,q<=100,T<=1000000,K<=1000000007,对于任意解密后的Q,有Q<=1000000



对于100%数据,有q>p,即0<= p/q<=1



这题还是比较水的,但听张一神说有毒,可能是我也有毒吧,233

考虑,在奇数层是不可能死的

因为如果在奇数层死,需要在上一个偶数层就出现了1的差距,这是不可能的

所以考虑所有偶数层

     0             0

    / \

    0   0           1

   /\   / \

  0  0  0  0       2

从我画的

#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<queue>
#include<map>
#include<cstdlib>
#include<algorithm>
#define V 32
#define mod 1000000007
#define LL long long
using namespace std;
int n;
LL p,q,t,k;
LL pp,qq;
inline int qs( int x, int y)
{
      int i=1;
     for (;y;y>>=1,x=(LL)x*x%k)
     if (y&1)i=(LL)i*x%k;                        
     return i;  
}
inline void sd(LL &x,LL &y)
{
     LL ss=max(x,y);
     ss= sqrt (ss);
     for ( int i=2;i<=ss;i++)
     {
         while (x%i==0&&y%i==0)       
          {
            x/=i;
            y/=i;                        
          }  
     }
}
inline int haha()
{
     // freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);
     // freopen("brtree.in","r",stdin); freopen("brtree.out","w",stdout);
     int Q;
     LL ps,pd;
     cin>>p>>q>>t>>k;
     pp=-2*p*p+2*p*q;
       qq=q*q;
       LL A,B;
       A=2*p*p+q*q-2*q*p;
       B=q*q;
       sd(pp,qq);
       sd(A,B);
       int a=0,b;
       //int uu=0;
      // return 0;
     while (t--)
     {
           scanf ( "%d" ,&Q);
           Q-=a;
           //printf("%d\n",Q);
           if (Q%2!=0||Q<=0)
           {
             printf ( "0 0\n" );
             a=0;
             continue ;       
           }
           Q/=2;
           ps=qs(pp,Q-1);
           pd=qs(qq,Q-1);  
           a=ps*A%k;
           b=pd*B%k; 
           printf ( "%d %d\n" ,a,b); //return 0;
           //uu++;
           //if(uu==10)break;
           
     }
     return 0;
}
int gg=haha();
int main()
{;}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值