黑红树

问题 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
usingnamespacestd;
intn;
LL p,q,t,k;
LL pp,qq;
inlineintqs(intx,inty)
{
     inti=1;
    for(;y;y>>=1,x=(LL)x*x%k)
    if(y&1)i=(LL)i*x%k;                        
    returni;  
}
inlinevoidsd(LL &x,LL &y)
{
    LL ss=max(x,y);
    ss=sqrt(ss);
    for(inti=2;i<=ss;i++)
    {
        while(x%i==0&&y%i==0)       
         {
           x/=i;
           y/=i;                        
         }  
    }
}
inlineinthaha()
{
    // freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);
    // freopen("brtree.in","r",stdin); freopen("brtree.out","w",stdout);
    intQ;
    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);
      inta=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;
           
    }
    return0;
}
intgg=haha();
intmain()
{;}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值