[luogu3334]抛硬币

(数据范围的公式渲染有一些问题,大概是$a\le b\le 100$)

洛谷4548,推导过程省略,直接给出答案——

令$p_{H}=\frac{b}{a}$,$p_{T}=\frac{b}{b-a}$,则$pre_{i}=\prod_{j=0}^{i-1}P_{s_{j}}$($s$下标从为$[0,n)$)

令$S=\{i|s[0,i)=s[n-i,n)\}$,则答案为$\sum_{i\in S}pre_{i}$(本来是一个后缀除以整个串)

然后这道题的坑点在于要用分数表示,之后就需要高精度

通分即先将分母都改为$pre_{n}$的分母,之后分子计算需要高精乘和除单精,可以做到$o(L^{2})$

高精度gcd通过除以2以及相减可以做到$o(L^{2})$(其中$L=2\cdot 10^{3}+3$),要写成非递归形式,否则会MLE

高精度除法二分+暴力高精度乘法可以做到$o(L^{3})$(由于fft自带的常数,$o(L^{2}\log_{2}L)$甚至会TLE)

常数较大,大概可以压$10^{7}$(防止乘100后爆int)可以过

(事实上数据极水,不约分可以得到90分)

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define N 1005
  4 #define L (N<<1)
  5 #define ll long long
  6 #define base 10000000
  7 struct ji{
  8     int l,a[L];
  9 }zero,one,ans_zi,ans_mu,pre[N];
 10 int n,pa,pb,nex[N],rev[L<<1];
 11 char s[N];
 12 int cmp(ji x,ji y){//x<y则返回-1,x=y返回0,x>y返回1
 13     if (x.l!=y.l)return 1-(x.l<y.l)*2;
 14     for(int i=x.l;i;i--)
 15         if (x.a[i]!=y.a[i])return 1-(x.a[i]<y.a[i])*2;
 16     return 0;
 17 }
 18 ji add(ji x,ji y){
 19     x.l=max(x.l,y.l);
 20     for(int i=1;i<=x.l;i++){
 21         x.a[i]+=y.a[i];
 22         if (x.a[i]>=base){
 23             x.a[i]-=base;
 24             x.a[i+1]++;
 25         }
 26     }
 27     if (x.a[x.l+1])x.l++;
 28     return x;
 29 }
 30 ji dec(ji x,ji y){
 31     for(int i=1;i<=y.l;i++){
 32         if (x.a[i]<y.a[i]){
 33             x.a[i]+=base;
 34             x.a[i+1]--;
 35         }
 36         x.a[i]-=y.a[i];
 37     }
 38     while ((x.l>1)&&(!x.a[x.l]))x.l--;
 39     return x;
 40 }
 41 ji mul(ji x,int y){
 42     x.a[1]=x.a[1]*y;
 43     for(int i=2;i<=x.l;i++){
 44         x.a[i]=x.a[i]*y+x.a[i-1]/base;
 45         x.a[i-1]%=base;
 46     }
 47     if (x.a[x.l]>=base){
 48         x.a[x.l+1]=x.a[x.l]/base;
 49         x.a[x.l]%=base;
 50         x.l++;
 51     }
 52     return x;
 53 }
 54 ji mul(ji x,ji y){
 55     ji ans;
 56     ans.l=x.l+y.l-1;
 57     memset(ans.a,0,sizeof(ans.a));
 58     for(int i=1;i<=x.l;i++)
 59         for(int j=1;j<=y.l;j++){
 60             ll s=1LL*x.a[i]*y.a[j];
 61             ans.a[i+j]+=(ans.a[i+j-1]+s)/base;
 62             ans.a[i+j-1]=(ans.a[i+j-1]+s)%base;
 63         }
 64     if (ans.a[ans.l+1])ans.l++;
 65     return ans;
 66 }
 67 ji div(ji x,int y){
 68     int r=0;
 69     for(int i=x.l;i;i--){
 70         r+=x.a[i];
 71         x.a[i]=r/y;
 72         r=(r%y)*base;
 73     }
 74     if ((x.l>1)&&(!x.a[x.l]))x.l--;
 75     return x;
 76 }
 77 void write(ji x){
 78     printf("%d",x.a[x.l]);
 79     for(int i=x.l-1;i;i--){
 80         if (x.a[i]<1000000)printf("0");
 81         if (x.a[i]<100000)printf("0");
 82         if (x.a[i]<10000)printf("0");
 83         if (x.a[i]<1000)printf("0");
 84         if (x.a[i]<100)printf("0");
 85         if (x.a[i]<10)printf("0");
 86         printf("%d",x.a[i]);
 87     }
 88 }
 89 ji div(ji x,ji y){
 90     ji l=zero,r=x,mid;
 91     while (cmp(l,r)<0){
 92         mid=div(add(l,r),2);
 93         //write(l),printf(" "),write(r),printf(" "),write(mul(mid,y)),printf("\n");
 94         if (cmp(mul(mid,y),x)<0)l=add(mid,one);
 95         else r=mid;
 96     }
 97     return l;
 98 }
 99 ji gcd(ji x,ji y){
100     int cnt=0,deep=0;
101     while (cmp(x,y)){
102         int p1=(x.a[1]&1),p2=(y.a[1]&1);
103         if ((p1)&&(p2)){
104             if (cmp(x,y)<0)y=dec(y,x);
105             else x=dec(x,y);
106             continue;
107         }
108         if (!p1)x=div(x,2);
109         if (!p2)y=div(y,2);
110         if ((!p1)&&(!p2))cnt++;
111     }
112     ji ans=x;
113     while (cnt--)ans=mul(ans,2);
114     return ans;
115 }
116 int main(){
117     scanf("%d%d%s",&pa,&pb,s);
118     n=strlen(s);
119     zero.l=one.l=one.a[1]=1;
120     ans_mu=one;
121     for(int i=0;i<n;i++)
122         if (s[i]=='H')ans_mu=mul(ans_mu,pa);
123         else ans_mu=mul(ans_mu,pb-pa);
124     pre[0]=ans_mu;
125     for(int i=0;i<n;i++){
126         pre[i+1]=mul(pre[i],pb);
127         if (s[i]=='H')pre[i+1]=div(pre[i+1],pa);
128         else pre[i+1]=div(pre[i+1],pb-pa);
129     }
130     nex[0]=nex[1]=0;
131     for(int i=1,j=0;i<n;i++){
132         while ((j)&&(s[i]!=s[j]))j=nex[j];
133         if (s[i]==s[j])j++;
134         nex[i+1]=j;
135     }
136     for(int i=n;i;i=nex[i])ans_zi=add(ans_zi,pre[i]);
137     ji d=gcd(ans_zi,ans_mu);
138     write(div(ans_zi,d));
139     printf("/");
140     write(div(ans_mu,d));
141 }
View Code

 

posted @ 2020-12-31 15:34  PYWBKTDA  阅读(188)  评论(0编辑  收藏  举报