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)