2024.7 總結

dijah發表於2024-07-05

資料結構

【CF380C】 Sereja and Brackets

題目描述

  • 本題中「合法括號串」的定義如下:
    • 空串是「合法括號串」。
    • \(s\) 是「合法括號串」,則 \((s)\) 是「合法括號串」。
    • \(s,t\) 是「合法括號串」,則 \(st\) 是「合法括號串」。
  • 有一個括號串 \(s\)\(m\) 次操作。操作有一種:
    1. 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;
}