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;
}


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