这个题的亮点就是”它竟然是WC的题!!!!“
第二问的DP木有什么好说的
很裸的f[i]=(1<<i-sigma(f[j]*j)(j|i))/i,剩下的就是高精度的事了
然后关于第一问,首先本弱菜想了很久木有想出来原因竟然是我以为是要找前驱。。。。。。。
好吧,它是要找后继的说。。。。。
那么直接进入正题,对于一个合法序列a,说它合法有三个条件,没有后继0、没有循环节或循环长度为序列长度、然后就是对于连续的0的个数的最大值,就是前导0的个数。
那么序列a的后继怎么构造呢?首先对于无循环节我们不好保证,那么看如何保证第三个性质。
假设a的前导0个数为x,令序列b=0...01(即1前面x个0),分解a=b+c,(即将a的前导0和第一个1分离出来,剩下的为c)
那么显而易见a+b在a的后面且不存在d使得在满足第一个性质情况下a<d<a+b,但是a+b=b+c+b,由于是环b+c+b与b+b+c表示同一个且b+b+c在a的前面。
依次类推,可知,只在a后加入b序列是不可行的。
但不能就放弃这种构造了
那么设y为c的前导0的个数,e=0...01(即1前面y个0),又设z为c中连续0个数最大值,f=0...01(即1前面z个0),显然z>=y
对于a+b不合法,那么贪心的想a+b+f为另一构造,但是又由于环的可旋转性,a+b+f=b+c+b+f=b+f+b+c,而b+f+b+c<a所以下一阶段可加在a+b后的就是e。
所以递归下去,会发现,在不考虑循环节的情况下,a的后继竟然是a+a!!!!(若长度大于n则去掉大于n的尾部)
那么循环节呢?由于a+a已经是a在不考虑循环节时的后继了,那么,把新串看成二进制数后+1再去掉后继0就可以了。
但是,这还不一定是ans,考虑+1后,能影响到的是第二个a,如果长度小于n,那空出的位置不是浪费了?
所以,最后ans就是将a+a+a+a...这样自接很多遍,再将长度多出n的部分去掉,再看成二进制数+1,再去掉后继0就是了。
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#define mo 100000
struct highpre
{
int va[100];
int len;
} f[1005],ppo[1005];
int a[200005],n=0,m=0,key=0;
void muti(highpre &c,highpre &a,int b)
{
memset(c.va,0,sizeof(c.va));
c.len=0;
int i=0;
for (i=1;i<=a.len;i++)
{
c.va[i]=a.va[i]*b;
if (c.va[i-1]>=mo)
{
c.va[i]+=(c.va[i-1]/mo);
c.va[i-1]%=mo;
}
}
c.len=a.len;
while (c.va[c.len]>=mo)
{
c.va[c.len+1]=c.va[c.len]/mo;
c.va[c.len]%=mo;
c.len++;
}
}
void dec(highpre &a,highpre &b)
{
int i=0;
for (i=1;i<=a.len;i++)
{
if (a.va[i]>=b.va[i])
a.va[i]-=b.va[i];
else
{
while (a.va[i]<b.va[i])
{
a.va[i+1]--;
a.va[i]+=mo;
}
a.va[i]-=b.va[i];
}
}
while (a.va[a.len]==0)
a.len--;
}
void div(highpre &a,int b)
{
int i=0,now=0;
for (i=a.len;i>=1;i--)
{
now=now*mo+a.va[i];
a.va[i]=now/b;
now%=b;
}
while (a.va[a.len]==0) a.len--;
}
void print(highpre &a)
{
printf("%d",a.va[a.len]);
int i=0,tmp=0;
for (i=a.len-1;i>=1;i--)
{
if (a.va[i]==0)
tmp=5;
else
tmp=5-(int)(log10(a.va[i])+1);
for (;tmp>=1;tmp--)
printf("0");
printf("%d",a.va[i]);
}
printf("\n");
}
int main()
{
freopen("twins.in","r",stdin);
freopen("twins.out","w",stdout);
scanf("%d%d%d\n",&n,&m,&key);
int i=0,j=0;
char ch=0;
for (i=1;i<=m;i++)
{
scanf("%c",&ch);
a[i]=(int)(ch-'0');
}
for (i=m+1;i<=n;i++)
a[i]=a[((i-1)%m)+1];
a[n]++;
while (a[n]>1 && n>1)
{
a[n]=0;
n--;
a[n]++;
}
ppo[1].va[1]=2;
ppo[1].len=1;
f[1].va[1]=2;
f[1].len=1;
highpre tmp;
memset(tmp.va,0,sizeof(tmp.va));
tmp.len=0;
for (i=2;i<=key;i++)
{
muti(ppo[i],ppo[i-1],2);
memcpy(f[i].va,ppo[i].va,sizeof(ppo[i].va));
f[i].len=ppo[i].len;
for (j=1;j<i;j++)
if (i%j==0)
{
muti(tmp,f[j],j);
dec(f[i],tmp);
}
div(f[i],i);
}
print(f[key]);
for (i=1;i<=n;i++)
printf("%d",a[i]);
return 0;
}