牛客练习赛35 BCE题解

B.背单词

设d[ i ][ j ][ k ] 为在第从1到第 i 个字母,后缀连续长度为 j (j=0为元音,1位辅音)的种类数,很显然转移方程为:

d[ i ][ 0 ][ j+1 ]=d[ i-1 ][ 0 ][ j ]*5,辅音则乘以21,d[ i ][ 0 ][ 1 ]=5*( d[ i-1 ][ 1 ][ k ](k=1,2,,,B)),还有一个读者自己可以推,很简单。

#include
#define ll long long
using namespace std;
const int maxn=5005,mod=1e9+7;
ll d[maxn][2][55];
int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		int n,a,b;
		cin>>n>>a>>b;
		ll ans=0;
		for(int i=1;i<=n;i++)
		{
			ll res1=d[i-1][0][a],res2=d[i-1][1][b];
			for(int j=1;j=0)
			d[i][0][j+1]=d[i-1][0][j]*5%mod,res1+=d[i-1][0][j],ans+=d[i][0][j+1];
			for(int j=1;j=0)
			d[i][1][j+1]=d[i-1][1][j]*21%mod,res2+=d[i-1][1][j],ans+=d[i][1][j+1];
			if(i==1)
			res1=res2=1;	
			d[i][0][1]=res2*5%mod;
			d[i][1][1]=res1*21%mod;
			ans+=d[i][0][1];
			ans+=d[i][1][1];
		}
		cout<

C.函数的魔法

思路:因为最多只有233种情况,所以我只要从A开始跑bfs即可,很简单。

#include
#define ll long long
using namespace std;
int vis[250],d[250];
int dij(int s,int t)
{
	queueq;
	q.push(s);
	memset(vis,0,sizeof(vis));
	d[s]=0;
	while(!q.empty())
	{
		int x=q.front();q.pop();
		int y=(x*x*x+x*x)%233;
		if(!vis[y])
		{
			q.push(y);
			d[y]=d[x]+1;
			vis[y]=1;
			if(y==t)return d[y];
		}
		y=(x*x*x-x*x)%233;
		if(!vis[y])
		{
			q.push(y);
			d[y]=d[x]+1;
			vis[y]=1;
			if(y==t)return d[y];			
		}
	}
	return -1;
}
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		int a,b;
		scanf("%d%d",&a,&b);
		if(a==b)
		{
			puts("0");
			continue;
		}
		if(b>=233)
		{
			puts("-1");
			continue;
		}
		printf("%d\n",dij(a%233,b));
	}
}

E.μ‘s挑选比赛歌曲

思路:比赛时题意读漏了,赛后发现加特判就过了(被自己蠢哭了),首先我们要快速求出所有歌曲的最长公共子串长度,看是否超过K,怎么求呢?还记得后缀数组的height数组吗,没错,我们把所有歌曲拼接成一个字符串,然后求后缀数组,然后枚举height数组把所有长度超过k的不同后缀串用G数组标记,最后状态压缩枚举所有状态,用G数组判断该状态是否合法即可。

#include
using namespace std;
const int maxn=8e5+1000;
int G[25];
int id[maxn];
struct S_array
{
    int sa[maxn],t[maxn],t2[maxn],c[maxn],n;
    char  s[maxn];
    void build_sa(int m)
    {
        int i,*x=t,*y=t2;
        for(i=0;i=0;i--)sa[--c[x[i]]]=i;
        for(int k=1;k<=n;k<<=1){
            int p=0;
            for(i=n-k;i=k)y[p++]=sa[i]-k;
            for(i=0;i=0;i--)sa[--c[x[y[i]]]]=y[i];
            swap(x,y);
            p=1;x[sa[0]]=0;
            for(i=1;i=n)break;
            m=p;
        }
    }
    int rank[maxn],height[maxn];
    void getHeight()
    {
        int i,j,k=0;
        for(i=0;i=k)
        {
            vis[id[sa[i]]]=1;
            vis[id[sa[i-1]]]=1;
            flag=1;
        }
        else if(flag)
        {
            flag=0;
            for(int j=1;j<=20;j++)
            for(int p=1;p

 

你可能感兴趣的:(比赛----牛客练习赛题解)