CF 379D NewYearLetter [dp+暴力]

题意:

给出k,x,n,m

找出这样的字符串s1,s2,s1长为n,s2长为m

给出规则,sn=sn-1+sn-2

使得第Sk项出现x个"AC"子串

 

我们很容易知道k次运算后有几个12,几个21,几个22子串,有几个串1,有几个串2

如果我们知道s1中出现了几个AC,s2中出现了几个AC

s1头和尾,s2头和尾巴

我们就能算出k次后能出现几个AC

现在正好反过来,我们都不知道s1,s2,我们要找出这样的s1,s2

那么我们枚举

s1头和尾,s2头和尾巴

s1中出现了几个AC,s2中出现了几个AC

算出来的Sk里面出现的AC数和x是否相等

直到枚举出来这样的

没有的话就输出happy new year

 

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;
long long k,x,n,m;
long long lastnum[4][4];
long long num[4][4];
long long x1=1,x2=0;
long long xx1=0,xx2=1;
long long tmp[4][4];
void copy(long long to[][4],long long from[][4]){
	for(long long i=1;i<=2;i++)
		for(long long j=1;j<=2;j++)
			to[i][j]=from[i][j];
}
void add(long long to[][4],long long from[][4]){
	for(long long i=1;i<=2;i++)
		for(long long j=1;j<=2;j++)
			to[i][j]+=from[i][j];
}
long long ac_num(char* s){
	long long cnt=0;
	long long len=strlen(s);
	for(long long i=0;i<len;i++)
		if(s[i]=='A' && s[i]=='C') cnt++;
	return cnt;
}
bool can(long long num1,long long num2,long long suf1,long long suf2,long long pre1,long long pre2){
	if(xx1*num1+xx2*num2+
		num[1][2]*(suf1=='A' && pre2=='C')+
		num[2][2]*(suf2=='A' && pre2=='C')+
		num[2][1]*(suf2=='A' && pre1=='C')
		==x){
		///cout<<"n::"<<num[1][2]<<' '<<num[2][2]<<' '<<num[2][1]<<endl;
		return true;
	}else
		return false;
}
bool print(long long num1,long long num2, char suf1,char suf2,char pre1,char pre2){

        if(n==1 && pre1 != suf1) return false;
        if(m==1 && pre2 != suf2) return false;

	if(n%2==0){ if(num1==n/2) if(!(suf1=='C' && pre1=='A')) return false;
	}else if(num1==n/2)if ((!(pre1=='A'||suf1=='C'))&&(n!=1))return false;

	if(m%2==0){ if(num2==m/2) if(!(suf2=='C' && pre2=='A')) return false;
	}else if(num2==m/2) if ((!(pre2=='A'||suf2=='C'))&&(m!=1)) return false;

	if(n%2==0){
		if(num1==n/2){
			for(long long i=1;i<=num1;i++)	cout<<"AC";
		}else{
			cout<<pre1;
			for(long long i=1;i<=num1;i++)	cout<<"AC";
			for(long long i=1;i<=n-num1*2-2;i++)	cout<<"B";
			cout<<suf1;
		}
	}else{
		if(num1==n/2){
            if(n==1) cout<<pre1;
			else
                if(pre1=='A'){
                    for(long long i=1;i<=num1;i++)	cout<<"AC";
                    cout<<suf1;
                }else if(suf1=='C'){
                    cout<<pre1;
                    for(long long i=1;i<=num1;i++)	cout<<"AC";
                }
		}else{
			cout<<pre1;
			for(long long i=1;i<=num1;i++)	cout<<"AC";
			for(long long i=1;i<=n-num1*2-2;i++)	cout<<"B";
			cout<<suf1;
		}
	}
	cout<<endl;
	if(m%2==0){
		if(num2==m/2){
			for(long long i=1;i<=num2;i++)	cout<<"AC";
		}else{
			cout<<pre2;
			for(long long i=1;i<=num2;i++)	cout<<"AC";
			for(long long i=1;i<=m-num2*2-2;i++)	cout<<"B";
			cout<<suf2;
		}
	}else{
		if(num2==m/2){
            if(m==1) cout<<pre2;
			else
                if(pre2=='A'){
                    for(long long i=1;i<=num2;i++)	cout<<"AC";
                    cout<<suf2;
                }else if(suf2=='C'){
                    cout<<pre2;
                    for(long long i=1;i<=num2;i++)	cout<<"AC";
                }
		}else{
			cout<<pre2;
			for(long long i=1;i<=num2-1;i++)	cout<<"AC";
			for(long long i=1;i<=m-num2*2-2;i++)	cout<<"B";
			cout<<suf2;
		}
	}
	cout<<endl;
	return true;
}
int main(){
#ifndef ONLINE_JUDGE
	freopen("G:/in.txt","r",stdin);
#endif

	cin>>k>>x>>n>>m;
	for(long long i=3;i<=k;i++){
		long long xx1tmp=xx1,xx2tmp=xx2;
		xx1+=x1;xx2+=x2;
		x1=xx1tmp,x2=xx2tmp;
		copy(tmp,num);
		add(num,lastnum);
		copy(lastnum,tmp);
		if(i==3)        num[1][2]=1;
		if(i>=4 && i%2==0)
			num[2][1]++;
		else if(i>=4)
			num[2][2]++;
	}
	for(long long num1=0;num1<=(n/2);num1++)
		for(long long num2=0;num2<=(m/2);num2++)
			for(long long suf1='A';suf1<='C';suf1++)
				for(long long suf2='A';suf2<='C';suf2++)
					for(long long pre1='A';pre1<='C';pre1++)
						for(long long pre2='A';pre2<='C';pre2++)
							if(can(num1,num2,suf1,suf2,pre1,pre2)){
                                                                        ///cout<<xx1<<' '<<xx2<<endl;

//                                                                        cout<<num1<<' '
//                                                                        <<num2<<' '
//                                                                        <<(char)pre1<<' '
//                                                                        <<(char)pre2<<' '
//                                                                        <<(char)suf1<<' '
//                                                                        <<(char)suf2<<' '<<endl;

								if(print(num1,num2,suf1,suf2,pre1,pre2)){

									return 0;
                                                                }
							}
	cout<<"Happy new year!"<<endl;
}


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值