黑红树

背景

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	
2 3 2 100
1
2
样例输入2
2 3 2 20
4
6

样例输出

样例输出1	
0 0
5 9
样例输出2
0 1
0 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

 

solution:

 解法1:

考试时想的(能过8个点,手动开O3能A)

把图全画出来,你会得到一个通项公式:

f[i]=( (2*p*(q-p))^(h/2-1) * (2*p^2-2*q*p+q^2) ) / q^h

    =0   (h为奇数)

然后分解质因数约分即可

解法2:

我们发现h为奇数时只有可能  abs(黑点数-红点数)=1,所以 f[h]=0

当h为偶数时,

我们发现 (p/q)+(1+p/q)=(p^2+(q-p)^2)/q^2 为走两个高度时不掉的概率   而 1-(p^2+(q-p)^2)/q^2=2*p(q-p)/q^2 是掉的概率

我们设 掉概率分子为A,分母为B    不掉概率分子为C,分母为D

f[h]= 0     h为奇数

     = C^(h/2-1)*A  /  (B^2)^(h/2-1)*(D^2)

至于约分只要在一开始把A和B,C和D的约数约掉即可

 

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #include<cmath>
  5 #define ll long long
  6 #define mem(a,b) memset(a,b,sizeof(a))
  7 using namespace std;//5137
  8 int maxn(int a,int b){return a>b?a:b;}
  9 int abss(int x){return x<0?-x:x;}
 10 const int Max=50050;
 11 
 12 int prime[100001],num;
 13 bool he[100001];
 14 
 15 __attribute__((optimize("O3"))) void PRIME()
 16 {
 17     int q1=(int)ceil(sqrt(Max));
 18     for(int i=2;i<=Max;++i)
 19     {
 20         if(he[i])continue;
 21         prime[++num]=i;
 22         for(int j=i*2;j<=Max;j+=i)
 23             he[j]=1;
 24     }
 25 }
 26 
 27 
 28 
 29 int p,q,k,m;
 30 int h;
 31 ll a,b;
 32 
 33 __attribute__((optimize("O3"))) ll mi(ll x,ll c)
 34 {
 35     ll ans=1;
 36     while(c)
 37     {
 38         if(c&1)
 39           ans=ans*x%k;
 40         x=x*x%k;
 41         c>>=1;
 42     }
 43     return ans;
 44 }
 45 
 46 int azhi[5201],bzhi[5201];
 47 /*void out11()
 48 {
 49     printf("\n");
 50     for(int i=1;i<=20;++i)
 51       printf("%d ",azhi[i]);
 52     printf("\n");
 53     for(int i=1;i<=20;++i)
 54       printf("%d ",bzhi[i]);
 55     printf("\n");
 56 }*/
 57 __attribute__((optimize("O3"))) void qq()
 58 {
 59     if(h&1||h==0)
 60     {
 61         a=0;
 62         b=0;
 63         return ;
 64     }
 65     mem(azhi,0);
 66     mem(bzhi,0);
 67     int ci=h/2-1;
 68     int q1=2*q*q-2*p*q+p*p;
 69     int q2=2*q*(p-q);
 70     int q3=p;
 71     //printf("ci=%lld q1=%lld q2=%lld q3=%lld\n",ci,q1,q2,q3);
 72     int maxl=0;
 73     //cout<<1;
 74     int now=0;
 75     while(q2!=1)
 76     {
 77         ++now;
 78         while(!(q2%prime[now]))
 79         {
 80             q2/=prime[now];
 81             ++azhi[now];
 82         }
 83         azhi[now]*=ci;
 84     }
 85     maxl=maxn(maxl,now);
 86     
 87     now=0;
 88     while(q1!=1)
 89     {
 90         ++now;
 91         while(!(q1%prime[now]))
 92         {
 93             q1/=prime[now];
 94             ++azhi[now];
 95         }
 96     }
 97     maxl=maxn(maxl,now);
 98     
 99     now=0;
100     while(q3!=1)
101     {
102         ++now;
103         while(!(q3%prime[now]))
104         {
105             q3/=prime[now];
106             ++bzhi[now];
107         }
108         bzhi[now]*=h;
109     }
110     maxl=maxn(maxl,now);
111     
112     for(int i=1;i<=maxl;++i)
113     {
114         if(azhi[i]>bzhi[i]){azhi[i]-=bzhi[i];bzhi[i]=0;}
115         else{bzhi[i]-=azhi[i];azhi[i]=0;}
116     }
117     //out11();
118     a=1;b=1;
119     for(int i=1;i<=maxl;++i)
120     {
121         if(azhi[i])
122           a=(a*(mi(prime[i],azhi[i])%k))%k;
123         if(bzhi[i])
124           b=(b*(mi(prime[i],bzhi[i])%k))%k;
125     }
126 }
127 
128 __attribute__((optimize("O3"))) int main(){
129     //freopen("1.txt","r",stdin);
130     //freopen("brtree7.in","r",stdin);
131     //freopen("brtree.out","w",stdout);
132     PRIME();
133     //printf("num=%d\n",num);
134     //out11();
135     scanf("%d%d%d%d",&q,&p,&m,&k);
136     
137     while(m--)
138     {
139         scanf("%d",&h);
140         h-=a%k;
141         qq();
142         //printf("caocoaca\n");
143         printf("%lld %lld\n",a,b);
144     }
145     //printf("\nend\n");
146     //while(1);
147     return 0;
148 }
解法1
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<cmath>
 5 #define ll long long
 6 #define mem(a,b) memset(a,b,sizeof(a))
 7 using namespace std;
 8 ll gcd(ll x,ll y){return y==0?x:gcd(y,x%y);}
 9 
10 ll a[1000010],b[1000010];
11 ll q,p,m,k,h;
12 
13 int main(){
14     //freopen("brtree4.in","r",stdin);
15     //freopen("2.txt","w",stdout);
16     scanf("%lld%lld%lld%lld",&p,&q,&m,&k);
17     //C:fall
18     ll A=2*p*(q-p),B=q*q,C=2*p*p-2*p*q+q*q,D=q*q;
19     while(1)
20     {
21         ll hh=gcd(A,B);
22         if(hh==1)break;
23         A/=hh;B/=hh;
24     }
25     while(1)
26     {
27         ll hh=gcd(C,D);
28         if(hh==1)break;
29         C/=hh;D/=hh;
30     }
31     ll nowa=1,nowb=1;
32     for(int i=2;i<=1000000;i+=2)
33     {
34         a[i]=nowa*C%k;
35         b[i]=nowb*D%k;
36         nowa=nowa*A%k;
37         nowb=nowb*B%k;
38     }
39     
40     //printf("%lld %lld\n",a[1000000],b[1000000]);
41     
42     ll aa=0,bb=0;
43     while(m--)
44     {
45         scanf("%lld",&h);
46         h-=(aa%k);
47         //printf("h=%d\n",h);
48         aa=a[h];bb=b[h];
49         printf("%lld %lld\n",aa,bb);
50     }
51     //while(1);
52     return 0;
53 }
解法2

 

posted @ 2017-07-28 20:09  A_LEAF  阅读(539)  评论(0编辑  收藏  举报