6692. 2020.06.05省选模拟灵符「无寿之梦」

Posted gmh77

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了6692. 2020.06.05省选模拟灵符「无寿之梦」相关的知识,希望对你有一定的参考价值。

题目描述

幽幽子得到了一个长度为 n 的,每个位置均为 * 或 + 的序列
她定义一个序列的权值为:最开始有一个数字 0,从左到右考虑序列的每个位置,如果为 * 则当前数字
*2,如果为 + 则当前数字 +1,最后得到的数字对 2^k 取模之后的结果
幽幽子想要知道,她得到的序列中,权值最大的子序列的权值是多少。

技术图片

题解

明明是2卡为什么这么难啊

可以发现这么一个东西:当有大于2个加号时*++等价于+*

所以可以不断向前合并变成每段加号只有最多两个,和只有一个加号的性质很像

从高位往低位构造,根据每个加号后面的乘号个数可以算出位数(两个+可以当作一个*)

如果到了某一位不能放1了就把后面的操作全部丢进去,类似高精度加法即可求出答案

code

#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
#define ll long long
#define file
using namespace std;

int a[1000101],ans[1000101],n,K,i,j,k,l,tot,len;
char st[1000001];

void put(int t)
{
	int i,j,k,l;
	fo(i,0,t) ans[i]+=a[i],ans[i+1]+=ans[i]/2,ans[i]%=2;
}

int main()
{
	freopen("dream.in","r",stdin);
	#ifdef file
	freopen("dream.out","w",stdout);
	#endif
	
	scanf("%d%d",&n,&K);
	scanf("%s",st+1);
	
	j=0;
	fd(i,n,1) if (st[i]==‘+‘) ++a[j],tot=max(tot,j); else ++j;
	fo(i,0,tot-1) if (a[i]>2) a[i+1]+=(a[i]-1)/2,a[i]-=((a[i]-1)/2)*2;
	while (a[tot]>2) a[tot+1]+=(a[tot]-1)/2,a[tot]-=((a[tot]-1)/2)*2,++tot;
	
	len=0;
	fd(i,K-1,0)
	if ((tot+(a[tot]==2))>=i)
	{
		ans[i]=1;--tot;
		while (tot>0 && !a[tot]) --tot;
		if (tot<0) break;
	}
	else
	{put(tot);break;}
	
	j=K-1;while (j && !ans[j]) --j;
	fd(i,j,0) printf("%d",ans[i]); printf("
");
	
	fclose(stdin);
	fclose(stdout);
	return 0;
}



以上是关于6692. 2020.06.05省选模拟灵符「无寿之梦」的主要内容,如果未能解决你的问题,请参考以下文章

6691. 2020.06.05省选模拟六道剑「一念无量劫」

6691. 2020.06.05省选模拟六道剑「一念无量劫」

JZOJ 6693. 2020.06.05省选模拟紫色彼岸樱推迟绽放 (自然数幂拆上升幂+组合意义矩阵乘法+NTT)

JZOJ 6693. 2020.06.05省选模拟紫色彼岸樱推迟绽放 (自然数幂拆上升幂+组合意义矩阵乘法+NTT)

省选模拟(66~70)

省选模拟1