WC 2004 twins

这个题的亮点就是”它竟然是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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章