zoukankan      html  css  js  c++  java
  • [整理]NOI Online 2021第一场题解

    0.Preface

    考试的时候一如既往地被爆踩了/ll
    西西弗出题越来越不正经了
    Notice:这篇题解同时包含了提高组前两题入门组的(简化版)题目与解法,对于提高组试题提供了代码。

    1.Senior

    T1

    对于无限 Thue-Morse 数列 ({t_i}) 的前 (n) 项和给定多项式 (f),求 (sumlimits_{i=0}^{n-1}t_if(i))
    首先来对这个式子进行乱搞,设 (p_n)(n) 的二进制表示中 (1) 的个数,则找规律易知 (t_i=p_imod2)(dfrac12 [1-(-1)^{p_i}])
    那么此时答案就拆成了两个稍简单的式子:(dfrac12[sumlimits_{i=0}^{n-1}f(i)-sumlimits_{i=0}^{n-1}(-1)^{p_i}f(i)])
    前一个式子是 (k-1) 次多项式的前缀和,可以参照此题插值求出,重点在后一个式子。
    与前一个式子一样,求和的重点是 (sumlimits_{i=0}^{n-1}(-1)^{p_i}i^k)
    由于题目暗示得很明显,我们可以尝试将 ([0,n)) 拆分成几个区间,而区间之间要有一些关系可以方便地进行平移等操作。
    对于一个数 (n),我们把它从高位到低位划分就可以得到一些特殊性质,以下给出了一个例子。
    (n=(1010110)_2),我们将其分为四个区间:
    ([0000000,1000000)cup[10000000,1010000)cup[1010000,1010100)cup[1010100,1010110))
    接下来我们的任务就是对于每个偏移量 (d) 和某一位 (t),计算 (f_{d,t,k}=sumlimits_{i=0}^{2^t-1}(-1)^{p_{(i+d)}} (i+d)^k)
    这时候划分方式的作用就体现出来了:从 (d)(d+2^t-1) 这些数变化的数位对 (d) 没有影响,所以这个式子可变形为 ((-1)^{p_d}sumlimits_{i=0}^{2^t-1}(-1)^{p_i}(i+d)^k)
    把后面的幂暴力展开再蹂躏一番得到以下式子:(f_{d,t,k}=(-1)^{p_d}sumlimits_{j=0}^kdbinom{k}{j}d^{k-j}f_{0,t,j})
    所有 (f_{0,t,j}=f_{0,t-1,j}+f_{2^{t-1} ,t-1,j}) 可以倍增预处理出来,最终总复杂度为 (O(k^2(log n+k)))
    但是,这样是不够好的!我们需要优化!
    有些题解里直接根据打表得出结论是不妥当的,这里参考官方题解给出一个简易证明:
    首先推得 (f_{2^t,t,j}=-sumlimits_{i=0}^jdbinom{j}{i}2^{t(j-i)}f_{0,t,i})(显然)
    所以 (f_{0,t+1,j}) 就等于 (f_{0,t,j}) 加上上面的东西。
    证明:(t>j)(f_{0,t,j}=0)
    运用数学归纳法:固定一个 (j),显然 (t=0) 时成立。考虑 (t') 成立时证明 (t=t'+1) 也成立。
    1.若 (j=t'),则 (f_{0,t,j}=f_{0,j,j}-sumlimits_{i=0}^{j}dbinom{j}{i}2^{j(j-i)}f_{0,j,i}=f_{0,j,j}-f_{0,j,j}-sumlimits_{i=0}^{j-1}dbinom{j}{i}2^{j(j-i)}f_{0,j,i}=0-0-0=0)
    2.若 (j<t'),则 (f_{0,t,j}=f_{0,t',j}-sumlimits_{i=0}^jdbinom{j}{i}2^{t'(j-i)}f_{0,t',i}=0-0=0)
    所以 (t>j)(f_{0,t,j}=0)(lacksquare)
    如果还不明白的话请看更详细的草稿吧(虽然根本看不清楚)
    cg
    可以明显看出作者快证出来时笔法逐渐猖狂
    由于作者水平所限,如证明过程出现纰漏敬请指出。
    关于代码实现,先插值求出减号前部分,再利用公式计算减号后的部分,有非常多的细节,请仔细编写(我是照着洛谷题解改的)
    一些预处理的总复杂度为 (O(log n)),减号前复杂度为 (O(k^2)),减号后复杂度为 (O(k^3)),最终总复杂度为 (O(log n+k^3))

    const int N=500010,K=510,p=1000000007;
    int n,nn,k,a[K],ans1,ans2;char s[N];
    int C[K][K],pw2[N];
    il void Init(){
      for(rg int i=0;i<=k;i++){
        C[i][0]=C[i][i]=1;
        for(rg int j=1;j<i;j++){
          C[i][j]=(C[i-1][j]+C[i-1][j-1])%p;
        }
      }
      pw2[0]=1;
      for(rg int i=1;i<=n;i++)pw2[i]=2ll*pw2[i-1]%p;
      for(rg int i=0;i<n;i++)nn=(2ll*nn+s[i]-48)%p;
      nn=(nn-1+p)%p;
    }
    il int Pow(int a,int b){
      int res=1;
      while(b){
        if(b&1)res=res*a%p;
        a=a*a%p,b>>=1;
      }
      return res;
    }
    int f[K][K];
    //f_{t,j}=f_{t-1,j}-sum_iinomji 2^{t(j-i)}f_{t,i}
    il int Calc(int t,int j){
      if(t>j)return 0;
      if(f[t][j]!=-1)return f[t][j];
      if(!t)return j==0;
      int res=Calc(t-1,j),pw=pw2[t-1],w=1;
      for(rg int i=j;i>=0;i--,w=w*pw%p){
        res=(res-C[j][i]*w%p*Calc(t-1,i)%p+p)%p;
      }
      return f[t][j]=res;
    }
    int fac[K],inv[K],pre[K],suf[K];
    il int CalcFunc(int x){//Calculate f
      int res=0;
      for(rg int i=k-1;i>=0;i--){
        res=(1ll*res*x%p+a[i])%p;
      }
      return res;
    }
    int sumf[K],ff[K];
    il void InitLagrange(){
      fac[0]=pre[0]=suf[k+2]=1;
      for(rg int i=1;i<=k+1;i++)fac[i]=fac[i-1]*i%p;
      inv[k+1]=Pow(fac[k+1],p-2);
      for(rg int i=k;i>=0;i--)inv[i]=inv[i+1]*(i+1)%p;
      sumf[0]=CalcFunc(0);
      for(rg int i=1;i<=k+1;i++){
        sumf[i]=(sumf[i-1]+CalcFunc(i))%p;
        ff[i]=sumf[i]*inv[i-1]%p*inv[k+1-i]%p;
        if((i^k+1)&1)ff[i]=p-ff[i];
      }
    }
    il int Lagrange(int m){
      int res=0;
      for(rg int i=1;i<=k+1;i++)pre[i]=pre[i-1]*(m-i)%p;
      for(rg int i=k+1;i;i--)suf[i]=suf[i+1]*(m-i)%p;
      for(rg int i=1;i<=k+1;i++){
        res=(res+ff[i]*pre[i-1]%p*suf[i+1]%p)%p;
      }
      return res;
    }
    void Solve(){
      int lst=0,lpp=0;
      for(rg int i=0;i<n;i++){
        int t=n-i-1;
        int now=(2ll*lst+s[i]-48)%p,pp=lpp^(s[i]-48);
        if(t>k){
          lst=now,lpp=pp;continue;
        }
        if(s[i]==49){
          int pw=lst*pw2[t+1]%p;
          for(rg int j=0;j<k;j++){
            int sum=0,w=1;
            for(rg int l=j;l>=0;l--,w=w*pw%p){
              sum=(sum+C[j][l]*w%p*Calc(t,l)%p)%p;
            }
            if(lpp)sum=p-sum;
            ans2=(ans2+a[j]*sum%p)%p;
          }
        }
        lst=now,lpp=pp;
      }
    }
    signed main(){
      memset(f,-1,sizeof(f));
      scanf("%s",s),n=strlen(s);
      Read(k);
      for(rg int i=0;i<k;i++)Read(a[i]);
      Init(),InitLagrange(),ans1=Lagrange(nn);
      Solve();
      int ans=(ans1-ans2+p)%p*((p+1)/2)%p;
      cout<<ans<<endl;
      KafuuChino HotoKokoa
    }
    

    所以 €€£ 是玩自然数幂和玩上瘾了吗

    T2

    给定两字符串(s,t),求(s)中有多少种子序列能够对应(t)中一子段
    枚举 (t) 的子串然后从 (s) 中顺次匹配即可(具体见代码),至于去重可以存一下哈希值。

    const int N=3010,bas=13331,mod=1991122519911223;//关于模数和进制:能过就行
    int n;char s[N],t[N];
    int q[N*N];
    signed main(){
      scanf("%lld%s%s",&n,s+1,t+1);
      for(rg int i=1;i<=n;i++){
        int val=0,p=1;
        for(rg int j=i;j<=n;j++){
          while(p<=n&&s[p]!=t[j])p++;
          if(p>n)break;
          val=(1ll*val*bas%mod+t[j]-96)%mod;
          q[++q[0]]=val;
          p++;
        }
      }
      sort(q+1,q+1+q[0]);
      cout<<unique(q+1,q+1+q[0])-q-1<<endl;
      KafuuChino HotoKokoa
    }
    

    T3

    (n)个点分别有两个权值(a_i,b_i),给定多组(l,r,c,d),求(#{xin[l,r]|a_x ext{xor} clemin{b_x,d}})
    不会,爬了。

    2.Junior

    T1

    一个圆只能沿直径切,最少切多少刀能切出(a:b:c)
    容易证明,最多只需要切三次,于是对不同情况分类讨论。

    T2

    在一个(n)阶方阵上找两条路径使得两条路径的权值和最大
    路径指按照(45^circ)直走(遇墙反弹)出的回路
    发现路径只有 (O(n)) 条,那么把所有路径预处理出来,枚举两条路径再特判重复的点即可(可能需要亿些分类讨论)。

    T3

    一个(n)阶方阵上有一些障碍和两个球,求按照 2048 的规则将两球合并的最小滑动次数
    由移动规则可知,只有障碍物(包括边界)周围的四个点是可以到达的,所以把这些状态记下来,再在可达的状态之间连边。
    状态比较多,我们考虑从最终重合的状态逆推,用 BFS 求出最短路即可。

    内容来自_ajhfff_的博客(https://www.cnblogs.com/juruoajh/),未经允许,不得转载。
  • 相关阅读:
    实现一个简易版的react
    浅学virtualDom和diff算法
    148. 排序链表 归并排序 | 快速排序
    OC中的NSDictionary和NSMutableDictionary
    OC中的block
    OC中的category&Extension
    OC中判断方法是否实现
    OC的分组导航标记
    OC中程序的内存分布&类加载
    OC中的@property和@synthesize
  • 原文地址:https://www.cnblogs.com/juruoajh/p/14588881.html
Copyright © 2011-2022 走看看