資料結構
【CF380C】 Sereja and Brackets
題目描述
- 本題中「合法括號串」的定義如下:
- 空串是「合法括號串」。
- 若 \(s\) 是「合法括號串」,則 \((s)\) 是「合法括號串」。
- 若 \(s,t\) 是「合法括號串」,則 \(st\) 是「合法括號串」。
- 有一個括號串 \(s\)。\(m\) 次操作。操作有一種:
l r
:求字串 \(t=s_ls_{l+1}\cdots s_r\) 的所有 子序列 中,長度最長的「合法括號串」,輸出長度即可。
- \(1\le |s|\le 10^6\),\(1\le m\le 10^5\)。
解題思路
首先,將 \((,)\) 轉化成 \(+1,-1\) ,就是找一個子序列,使得所有的字首和 \(\ge 0\) ,最後一個字首和為 \(0\) 。
我們考慮使用線段樹,維護沒能匹配的 \((\) 數量與沒能匹配的 \()\) 數量。
每次兩個區間合併時,就是將兩區間沒匹配的 \(()\) 個配對了進行計算即可。
由於我們預設沒匹配的 \((\) 儘量靠前,沒匹配的 \()\) 儘量靠後,不會出現匹配不了的問題。
時間複雜度 \(O(nlogn)\) 。
Code
#include<bits/stdc++.h>
using namespace std;
struct datay
{
int v1,v2;
}f[4000005];
string a;
int n,m;
void build(int x,int l,int r)
{
if(l==r)
{
if(a[l]=='(')f[x].v1=1,f[x].v2=0;
else f[x].v1=0,f[x].v2=1;
return;
}
int lc=(x<<1),rc=(x<<1)|1,mid=(l+r)>>1;
build(lc,l,mid),build(rc,mid+1,r);
f[x].v1=f[lc].v1+f[rc].v1-min(f[lc].v1,f[rc].v2);
f[x].v2=f[lc].v2+f[rc].v2-min(f[lc].v1,f[rc].v2);
return;
}
datay query(int x,int l,int r,int ql,int qr)
{
if(ql<=l&&r<=qr)return f[x];
int mid=(l+r)>>1,lc=(x<<1),rc=(x<<1)|1;
if(qr<=mid)return query(lc,l,mid,ql,qr);
if(ql>mid)return query(rc,mid+1,r,ql,qr);
datay z,q=query(lc,l,mid,ql,qr),w=query(rc,mid+1,r,ql,qr);
z.v1=q.v1+w.v1-min(q.v1,w.v2);
z.v2=q.v2+w.v2-min(q.v1,w.v2);
return z;
}
int main()
{
int x,y;datay z;
cin>>a,n=a.size();
a=' '+a,build(1,1,n);
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y),z=query(1,1,n,x,y);
printf("%d\n",y-x+1-z.v1-z.v2);
}
return 0;
}
【夢熊】 對稱之美
題目描述
給出 \(n,k\) \((1 \le n,k \le 10^{14})\) ,求 \(\sum_{i=0}^{k-1} C_{2i}^i n^i (mod\) \(k)\) 。
解題思路
首先,列舉可得,\(k=2\) 時答案為 \(1\) 。
\[C_{2n}^n=\frac{(2n)!}{n! \times n!} =2^n \times \frac{1 \times 3 \times ... \times (2n-1)}{n!} = (-2)^n \times \frac{\prod_{i=0}^{n-1}(k-1-2i)}{n!}=(-4)^n \times \frac{\prod_{i=0}^{n-1}(\frac{k-1}{2}-i)}{n!}
\]
帶回原式並化簡,即為:
\[\sum_{i=0}^{k-1} (-4n)^i \times C_{\frac{k-1}{2}}^{i}=(1-4n)^{\frac{k-1}{2}}
\]
結合二項式定理,由於 \(k\) 較大,需用龜速乘,結合快速冪 \(O(log^2n)\) 解決。
Code
#include<bits/stdc++.h>
using namespace std;
unsigned long long mod;
unsigned long long mul(unsigned long long x,unsigned long long y)
{
unsigned long long h=0;
while(y>0)
{
if(y&1)h=(h+x)%mod;
x=(x+x)%mod,y/=2;
}
return h;
}
unsigned long long poww(unsigned long long x,unsigned long long y)
{
x=(x+mod)%mod;
unsigned long long h=1;
while(y>0)
{
if(y&1)h=mul(h,x);
x=mul(x,x),y/=2;
}
return h;
}
void poi()
{
unsigned long long x,y;
cin>>x>>y;
if(x==1)
{
printf("1\n");
return;
}
mod=x;
cout<<(poww((4*mod+1-4*y)%mod,(mod-1)/2)+mod)%mod<<'\n';
return;
}
int main()
{
unsigned long long qwe;
cin>>qwe;
for(int i=1;i<=qwe;i++)poi();
return 0;
}