由此开始的记录

从现在开始做的题就往这里放放了,写不写题解,随缘。

这篇博客名来自 Charlotte 大结局的名字。

\(\text{CF149D Coloring Brackets}\)

/*
直接区间 dp,经典的,显然 f[l][r] 表示 [l,r] 的涂色方案。
f[l][r] 没法转移,因为不会判相邻颜色是否相同。
那么记一下两端颜色,因为你 r+1 不可能和 r-1 冲突。
f[l][r][x][y] 表示左端点颜色 x,右端点 y 的方案
为了方便,我们用记忆化搜索,这样可以钦定 l 处是左括号。
如果 l,r 就是匹配的括号,那么显然的 f[l][r][x][y]=sum {f[l+1][r-1][x'][y']}
如果 l,r 并不匹配,那么由于钦定过,我们可以把这个区间换成这样:
(...)(...)(...)...
然后乘法原理,方案数就是
f[ (...) ] * f[ (...)(...)... ] 
*/
#include <bits/stdc++.h>
#define rep(i,l,r) for(i=l;i<=r;++i)
using namespace std;
const int N=705,p=1e9+7;
char str[N];
long long f[N][N][3][3];
int ord[N];
inline void dfs(int l,int r)
{
	int i,j,a,b,c,d;
	if(l+1==r)
	{
		f[l][r][0][1]=f[l][r][1][0]=f[l][r][0][2]=f[l][r][2][0]=1;
		return ;
	}
	if(ord[l]==r)
	{
		dfs(l+1,r-1);
		rep(i,0,2)rep(j,0,2)
		{
			if(i!=1)(f[l][r][1][0]+=f[l+1][r-1][i][j])%=p;
			if(i!=2)(f[l][r][2][0]+=f[l+1][r-1][i][j])%=p;
			if(j!=1)(f[l][r][0][1]+=f[l+1][r-1][i][j])%=p;
			if(j!=2)(f[l][r][0][2]+=f[l+1][r-1][i][j])%=p;
		}
	}else
	{
		dfs(l,ord[l]);dfs(ord[l]+1,r);
		rep(a,0,2)rep(b,0,2)rep(c,0,2)rep(d,0,2)
		{
			if(b==c && b)break;
			(f[l][r][a][d]+=(f[l][ord[l]][a][b]*f[ord[l]+1][r][c][d]%p))%=p;
		}
	}
	return ;
}
int main()
{
	int n,i,j;
	stack<int> q;
	scanf("%s",str+1);n=strlen(str+1);
	rep(i,1,n)
	{
		if(str[i]=='(')q.push(i);
		else
		{
			ord[q.top()]=i;
			q.pop();
		}
	}
	dfs(1,n);
	long long ret=0;
	rep(i,0,2)rep(j,0,2)ret+=f[1][n][i][j];
	printf("%lld",ret%p);
	return 0;
}

upd on 23-7-10 12:01

\(\text{P4342 [IOI1998] Polygon}\)

/*
断环成链是显然的。断成 2n 之后,f[l][r] 表示合并 [l,r] 的最大值。
先考虑加法,显然 f[l][r]=max{f[l][k]+f[k+1][r]}
对于乘法,考虑到会出现傻逼的负负得正,必须存一个最小值,设这个是 g[l][r]
f[l][r]=max{mxval(l,k,r)}
g[l][r]=min{mnval(l,k,r)}
mxval(l,k,r)=max(f[l][k]*f[k+1][r],f[l][k]*g[k+1][r],g[l][k]*f[k+1][r],g[l][k]*g[k+1][r])
mnval(l,k,r)=min(f[l][k]*f[k+1][r],f[l][k]*g[k+1][r],g[l][k]*f[k+1][r],g[l][k]*g[k+1][r])
*/
#include <bits/stdc++.h>
#define rep(i,l,r) for(i=l;i<=r;++i)
template<class T> inline T max(T head) {
    return head;
}
template<class T, typename... Args>inline T max(T head, Args... args) {
    T t = max<T>(args...);
    return (head > t)?head:t;
}
template<class T> inline T min(T head) {
    return head;
}
template<class T, typename... Args>inline T min(T head, Args... args) {
    T t = min<T>(args...);
    return (head < t)?head:t;
}
const int N=105;
char op[N];
int num[N],f[N][N],g[N][N];
int n,i,le,ret,l,r,k,j,x;
char c;
const int inf=(1<<15);
int main()
{
	scanf("%d",&n);
	rep(i,1,n)
	{
		scanf(" %c %d",&c,&x);
		op[i]=op[i+n]=c;
		num[i]=num[i+n]=x;
	}
	rep(i,1,2*n)rep(j,1,2*n)f[i][j]=-inf,g[i][j]=inf;
	rep(i,1,2*n)f[i][i]=g[i][i]=num[i];
	rep(le,2,n)
		rep(l,1,2*n-le+1)
		{
			r=l+le-1;
			rep(k,l,r-1)
			{
				if(op[k+1]=='x')
				{
					f[l][r]=max(f[l][r],f[l][k]*f[k+1][r],f[l][k]*g[k+1][r],g[l][k]*f[k+1][r],g[l][k]*g[k+1][r]);
					g[l][r]=min(g[l][r],f[l][k]*f[k+1][r],f[l][k]*g[k+1][r],g[l][k]*f[k+1][r],g[l][k]*g[k+1][r]);
				}else
				{
					f[l][r]=max(f[l][r],f[l][k]+f[k+1][r]);
					g[l][r]=min(g[l][r],g[l][k]+g[k+1][r]);
				}
			}
//			printf("%d %d %d\n",l,r,f[l][r]);
		}
	rep(i,1,n)ret=max(ret,f[i][i+n-1]);
	printf("%d\n",ret);
	rep(i,1,n)if(f[i][i+n-1]==ret)
		printf("%d ",i);
	return 0;
}

upd on 23-7-10 12:44

\(\text{P3052 [USACO12MAR] Cows in a Skyscraper G}\)

/*
直接模拟退火啊。
*/
#include <bits/stdc++.h>
#define rep(i,l,r) for(i=l;i<=r;++i)
const int N=20;
int a[N];
int n,W,x,y,m,i;
using namespace std;
const double bT=1e5, eT=1e-3, derta=0.97;
inline int cost()
{
	int i, pre=0, ret=0;
	rep(i,1,n)
	{
		if(pre+a[i]>W)
		{
			++ret;
			pre=a[i];
		}else
			pre+=a[i];
	}
	return ret+(pre>0);
}
inline int SA()
{
	int ans=cost(), mid;
	for(double T=bT; T>=eT; T*=derta)
	{
		x=rand()%n+1;y=rand()%n+1;
		swap(a[x],a[y]);
		mid=cost();
		if(mid<ans)
			ans=mid;
		else if(exp((mid-ans)/T)<1.*rand()/RAND_MAX)
			swap(a[x],a[y]);	
	}
	return ans;;
}
int main()
{
	srand(8925);
	scanf("%d %d",&n,&W);
	auto beginning=clock();
	rep(i,1,n)scanf("%d",a+i);
	int ret=SA();
	while((clock()-beginning)*1.0/CLOCKS_PER_SEC <=0.9)ret=min(ret,SA());
	printf("%d",ret);
	return 0;
}

upd on 23-7-10 15:15

\(\text{CF629C Famil Door and Brackets}\)

/*
设 f[i][j] 表示前 i 个,cnt[(]-cnt[)] 的数量为 j 的方案数。
这个可以做出 P,Q 的样子啊。
接下来枚举 P 的长度,lp+lq+ls=n
然后枚举 P 的 cnt[(]-cnt[)] 的值。
需要满足 dertap+dertaq+dertas=0
直接乘法原理即可。
比如枚举出 p[lp][dertap],那么 lq=n-ls-lp, dertaq=-dertas-dertap
*/
#include <bits/stdc++.h>
#define int long long
#define rep(i,l,r) for(i=l;i<=r;++i)
using namespace std;
const int N=100005,p=1e9+7;
int f[2015][2015];
char str[N];
int i,j,x,mrex=p,n,m,ret;
inline void pre()
{
	f[0][0]=1;
	rep(i,1,2005)
	{
		f[i][0]=f[i-1][1];
		rep(j,1,i)f[i][j]=(f[i-1][j-1]+f[i-1][j+1])%p;//,printf("%d %d %d\n",i,j,f[i][j]);
	}
	return ;
}
inline int gmax()
{
	rep(i,1,m)
	{
		if(str[i]=='(')++x;else --x;
		mrex=min(mrex,x);
	}
	return mrex;
}
inline int solve()
{
	pre();
	gmax();
//	if(n>2000)printf("%d %d\n",x,mrex);
	rep(i,0,n-m)
		rep(j,0,i)
		{
			if(j>=-mrex && j+x<=n-m-i)
			{
//				printf("%d %d %d %d %d %d\n",i,j,f[i][j],n-m-i,j+x,f[n-m-i][j+x]);
				(ret+=(1ll*f[i][j]*f[n-m-i][j+x])%p)%=p;
			}
//			printf("%d %d %d\n", i, j, ret);
		}
	printf("%lld",ret);
	return 0;
}
signed main()
{
	scanf("%d %d %s", &n, &m, str+1);
	solve();
	return 0;
}

upd on 23-7-11 7:00

\(\text{P8675 [蓝桥杯 2018 国 B] 搭积木}\)

这题我随便写了个题解,可以去看看然后爆 down 我。

upd on 23-7-12 13:01

\(\text{P6218 [USACO06NOV] Round Numbers S}\)

#include <bits/stdc++.h>
using namespace std;
#define rep(i,l,r) for(i=l;i<=r;++i)
int f[75][75],l,r,i,j,cnt,lg[55];
inline int dp(bool limit,bool lzero,int dep,int derta)
{
	if(dep==0)return derta>=30;
	else if(!limit && !lzero && f[dep][derta]!=-1)return f[dep][derta];
	else
	{
		int ret=0,i,nxt=limit?lg[dep]:1;
		rep(i,0,nxt)
		{
			ret+=dp(limit&&(i==lg[dep]),lzero&&(i==0),dep-1,derta+(i==1?-1:(lzero?0:1)));
		}
		if(!limit && !lzero)f[dep][derta]=ret;
		return ret;
	}
}
int solve(int x)
{
	cnt=0;while(x)
	{
		lg[++cnt]=x&1;
		x>>=1;
	}
	return dp(1,1,cnt,30);
}
int main()
{
	int l,r;scanf("%d %d",&l,&r);
	rep(i,0,31)rep(j,0,61)f[i][j]=-1;
	printf("%d\n",solve(r)-solve(l-1));
	return 0;
}

upd on 23-7-13 23:43

\(\text{UVA1640 The Counting Problem}\)

双倍经验 \(\text{ SP3928 MDIGITS - Counting Digits}\)

#include <bits/stdc++.h>
using namespace std;
#define rep(i,l,r) for(i=l;i<=r;++i)
int f[15][15],lg[15];
int ret;
inline int dp(bool limit,bool lzero,int dep,int fl,int sum)
{
//	printf("%d %d %d %d %d\n",limit,lzero,dep,fl,sum);
	if(dep==0)
		return sum;
	if(!limit && !lzero && f[dep][sum]!=-1)return f[dep][sum];
	int ret=0,i,nxt=limit?lg[dep]:9;
	rep(i,0,nxt)ret+=dp(limit&&(i==lg[dep]),lzero&&(i==0),dep-1,fl,sum+(!(lzero&&(i==0))&&i==fl));//,printf("%d\n",i);//,printf("%d\n",ret);
	if(!limit && !lzero)f[dep][sum]=ret;
	return ret;
}
inline int solve(int v,int fl)
{int cnt,i,j;
	rep(i,0,12)rep(j,0,12)f[i][j]=-1;
	cnt=0;while(v)
	{
		lg[++cnt]=v%10;
		v/=10;
	}
	return dp(1,1,cnt,fl,0);
}
int main()
{int i,j,l,r;
//	printf("%d\n",solve(10,2));
	while(cin>>l>>r && (l||r))
	{if(l>r)swap(l,r);
		rep(i,0,8)printf("%d ",solve(r,i)-solve(l-1,i));
		printf("%d\n",solve(r,9)-solve(l-1,9));
	}
	return 0;
}

upd on 23-7-14 0:15

\(\text{CF855E Salazar Slytherin's Locket}\)

#include <bits/stdc++.h>
using namespace std;
using ll=long long;
ll f[15][70][1<<12];
ll lg[70];
int cnt,t,b;
ll l,r;
inline ll dp(bool limit,bool lzero,int dep,int sta,int b)
{
	if(dep==0)return sta==0;
	else if(!limit && !lzero && f[b][dep][sta]!=-1)return f[b][dep][sta];
	else
	{
		ll ret=0;
		int i,nxt=limit?lg[dep]:b-1;
		for(i=0;i<=nxt;++i)
			ret+=dp(limit&&(i==nxt),lzero&&(i==0),dep-1,(lzero&&i==0)?0:(sta^(1<<i)),b);
		if(!limit && !lzero)f[b][dep][sta]=ret;
		return ret;
	}
}
inline ll solve(ll x,int b)
{
	cnt=0;while(x)
	{
		lg[++cnt]=x%b;
		x/=b;
	}
	return dp(1,1,cnt,0,b);
}
int main()
{
	memset(f,-1,sizeof f);
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d %lld %lld",&b,&l,&r);
		printf("%lld\n",solve(r,b)-solve(l-1,b));
	}
}

upd on 23-7-14 12:03

SP10606 BALNUM - Balanced Numbers

#include <bits/stdc++.h>
using namespace std;
using ll=long long;
int f[20][1<<10][1<<10],lg[20];
int cnt;ll l,r;
inline bool check(int x,int y)
{
	for(int i=0;i<10;++i)
		if((x&(1<<i)) && ((i&1)==((y>>i)&1)))
				return false;
	return true;
}
inline ll dp(int limit,int lzero,int dep,int sta1,int sta2)
{
	if(dep==0)return check(sta1,sta2);
	else if(!limit && !lzero && f[dep][sta1][sta2]!=-1)return f[dep][sta1][sta2];
	else
	{
		ll ret=0;
		int i,nxt=limit?lg[dep]:9;
		for(i=0;i<=nxt;++i)
			ret+=dp(limit&&(i==nxt),lzero&&(i==0),dep-1,(lzero&&(i==0))?0:(sta1|(1<<i)),(lzero&&(i==0))?0:(sta2^(1<<i)));
		if(!limit && !lzero)f[dep][sta1][sta2]=ret;
		return ret;
	}
}
inline ll solve(ll x)
{
	cnt=0;while(x)
	{
		lg[++cnt]=x%10;
		x/=10;
	}
	return dp(1,1,cnt,0,0);
}
int main()
{
	memset(f,-1,sizeof f);
	int t;scanf("%d",&t);
	while(t--)
	{
		scanf("%lld %lld",&l,&r);
		printf("%lld\n",solve(r)-solve(l-1));
	}
	return 0;
}

upd on 23-7-14 12:25

P3810 【模板】三维偏序(陌上花开)

#include <bits/stdc++.h>
#define rep(i,l,r) for(i=l;i<=r;++i)
using namespace std;
const int N=1e5+5,V=2e5+5;
int ret[N];
int n,m,t,i,j,k;
class Eti
{
public:
	int a,b,c,cnt,res;
	inline const bool operator!=(const Eti &other)const
	{
		return a!=other.a || b!=other.b || c!=other.c;
	}
};
Eti e[N],ue[N];
class bit
{
public:
	int tr[V];
	inline void add(int x,int p)
	{
		while(x<=k)
		{
			tr[x]+=p;
			x+=(x&-x);
		}
	}
	inline int ask(int x)
	{
		int ret=0;
		while(x)
		{
			ret+=tr[x];
			x-=(x&-x);
		}
		return ret;
	}
}bit;
using cE=const Eti &;
inline const bool compareA(cE x,cE y)
{
	return x.a!=y.a?x.a<y.a:(x.b!=y.b?x.b<y.b:x.c<y.c);
}
inline const bool compareB(cE x,cE y)
{
	return x.b!=y.b?x.b<y.b:x.c<y.c;
}
inline void cdq(int l,int r)
{
	if(l==r) return ;
	int mid=l+r>>1;
	cdq(l,mid);cdq(mid+1,r);
	sort(ue+l,ue+mid+1,compareB);
	sort(ue+mid+1,ue+r+1,compareB);
	int i=l,j=mid+1;
	while(j<=r)
	{
		while(i<=mid && ue[i].b<=ue[j].b)
		{
			bit.add(ue[i].c,ue[i].cnt);
			++i;
		}
		ue[j].res+=bit.ask(ue[j].c);
		++j;
	}
	int k;
	rep(k,l,i-1)bit.add(ue[k].c,-ue[k].cnt);
}
int main()
{
	int i;
	scanf("%d %d",&n,&k);
	rep(i,1,n)scanf("%d %d %d",&e[i].a,&e[i].b,&e[i].c);
	sort(e+1,e+n+1,compareA);
	rep(i,1,n)
	{
		++t;
		if(e[i]!=e[i+1])
		{
			++m;
			ue[m]=e[i];
			ue[m].cnt=t;
			t=0;
		}
	}
	cdq(1,m);
	rep(i,1,n)ret[ue[i].res+ue[i].cnt-1]+=ue[i].cnt;
	rep(i,0,n-1)printf("%d\n",ret[i]);
	return 0;
}

upd on 23-7-14 23:41

posted @ 2023-07-14 23:45  Syara  阅读(23)  评论(0编辑  收藏  举报