2025年寒假算法天梯赛 03

C. 三人成行

  • 计数问题的核心是不重不漏。本题中,在同一个序列中合法的(x,y,z,u)可能在多个位置出现,为了避免重复,我们取最左边的位置作为代表,一旦符合题意就把它计入答案并终止后续的状态转移
  • 纠结局部会把自己弄晕的!拒绝晕倒,能不能从整体考虑,不记录当前的匹配情况,直接判定当前序列是否已经满足条件?完全可以!而且,一步步匹配一点都不美
  • 另一方面,你已经观察到使序列合法的子区间状态是有限的,进一步,这些合法状态完全可以通过压缩后缀和表示。而且,题目告诉你的条件是\(X+Y+Z \leq 17\),何必弱化为\(X,Y,Z \leq 15\)
#include <bits/stdc++.h>
using namespace std;
const int mod=1000000007;
long long f[45][1<<18],ans;
int n,X,Y,Z;
bool fx,fy,fz;
int i,l,s,t;
int power(int n,int p)
{
	if(p==0)
	{
		return 1;
	}
	long long tmp=power(n,p/2);
	if(p%2==1)
	{
		return tmp*tmp%mod*n%mod;
	}
	return tmp*tmp%mod;
}
void dfs(int n1)
{
	if(n1==-1)
	{
		if(fx&&fy&&fz)
		{
			ans=(ans+f[i][s]*power(10,n-i-1)%mod)%mod;
		}
		else
		{
			(f[i+1][t]+=f[i][s])%=mod;
		}
	}
	else
	{
		for(int i=0;i<2;i++)
		{
			if(n1+l<Z)
			{
				t=t+i*(1<<(n1+l));
			}
			if(i==1)
			{
				if(n1+l==X)
				{
					fx=true;
				}
				if(n1+l==Y)
				{
					fy=true;
				}
				if(n1+l==Z)
				{
					fz=true;
				}
			}
			s<<=1;
			s+=i;
			dfs(n1-1);
			s-=i;
			s>>=1;
			if(i==1)
			{
				if(n1+l==X)
				{
					fx=false;
				}
				if(n1+l==Y)
				{
					fy=false;
				}
				if(n1+l==Z)
				{
					fz=false;
				}
			}
			if(n1+l<Z)
			{
				t=t-i*(1<<(n1+l));
			}
		}
	}
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin>>n>>X>>Y>>Z;
	Y=X+Y;
	Z=Y+Z;
	f[0][1]=1;
	t=1;
	for(i=0;i<n;i++)
	{
		for(l=1;l<=10;l++)
		{
			dfs(Z-1);
		}
	}
	cout<<ans<<endl;
	return 0;
}

D. Yt函数

  • \(gcd(x,y)=gcd(x,n-x)=gcd(x,n)\)
posted @ 2025-02-08 23:09  D06  阅读(44)  评论(0)    收藏  举报
//雪花飘落效果