zoukankan      html  css  js  c++  java
  • [家里训练20_02_12]ABC

    A:CF1119H加强版,k<=10。

    不太想解释。

      1 #define mod 998244353
      2 #define G2 499122177
      3 #include<bits/stdc++.h>
      4 using namespace std;
      5 typedef long long int ll;
      6 int n,m,k,a[55],p[1000005][11],mask;
      7 ll f[1<<21],**g,val[1<<21];
      8 inline ll qpow(ll x,ll y)
      9 {
     10     ll ans=1,base=x;
     11     while(y)
     12     {
     13         if(y&1)
     14             ans=ans*base%mod;
     15         base=base*base%mod;
     16         y>>=1;
     17     }
     18     return ans;
     19 }
     20 inline void FWT(ll*A,int limit)
     21 {
     22     for(int len=2;len<=limit;len<<=1)
     23         for(int i=0;i<limit/len;++i)
     24             for(int j=0;j<len/2;++j)
     25             {
     26                 ll x=A[i*len+j],y=A[i*len+j+len/2];
     27                 A[i*len+j]=(x+y)%mod;
     28                 A[i*len+j+len/2]=(x-y+mod)%mod;
     29             }
     30 }
     31 inline void IFWT(ll*A,int limit)
     32 {
     33     for(int len=2;len<=limit;len<<=1)
     34         for(int i=0;i<limit/len;++i)
     35             for(int j=0;j<len/2;++j)
     36             {
     37                 ll x=A[i*len+j],y=A[i*len+j+len/2];
     38                 A[i*len+j]=(x+y)%mod*G2%mod;
     39                 A[i*len+j+len/2]=(x-y+mod)%mod*G2%mod;
     40             }
     41 }
     42 int main()
     43 {
     44     ios::sync_with_stdio(false);
     45     cin>>n>>m;
     46     k=3;
     47     for(int i=0;i<k;++i)
     48         cin>>a[i];
     49     for(int i=1;i<=n;++i)
     50     {
     51         for(int j=0;j<k;++j)
     52             cin>>p[i][j];
     53         mask^=p[i][0];
     54         for(int j=1;j<k;++j)
     55             p[i][j]^=p[i][0];
     56     }
     57     g=new ll*[1<<m];
     58     for(int i=0;i<(1<<m);++i)
     59     {
     60         g[i]=new ll[1<<(k-1)];
     61         for(int j=0;j<(1<<(k-1));++j)
     62             g[i][j]=0;
     63         g[i][0]=n;
     64     }
     65     for(int i=0;i<k;++i)
     66         val[0]=(val[0]+a[i])%mod;
     67     for(int S=1;S<(1<<(k-1));++S)
     68     {
     69         for(int i=0;i<(1<<m);++i)
     70             f[i]=0;
     71         val[S]=a[0];
     72         for(int j=0;j<k-1;++j)
     73             if(S&(1<<j))
     74                 val[S]=(val[S]-a[j+1]+mod)%mod;
     75             else
     76                 val[S]=(val[S]+a[j+1])%mod;
     77         for(int i=1;i<=n;++i)
     78         {
     79             int s=0;
     80             for(int j=0;j<k-1;++j)
     81                 if(S&(1<<j))
     82                     s^=p[i][j+1];
     83             ++f[s];
     84         }
     85         FWT(f,1<<m);
     86         for(int i=0;i<(1<<m);++i)
     87             g[i][S]=f[i];
     88     }
     89     ll G=qpow(1<<(k-1),mod-2);
     90     for(int i=0;i<(1<<m);++i)
     91     {
     92         IFWT(g[i],1<<(k-1));
     93         ll ans=1;
     94         for(int S=0;S<(1<<(k-1));++S)
     95             ans=ans*qpow(val[S],g[i][S])%mod;
     96         f[i]=ans;
     97     }
     98     IFWT(f,1<<m);
     99     for(int i=0;i<(1<<m);++i)
    100         cout<<f[i^mask]<<" ";
    101     cout<<endl;
    102     return 0;
    103 }
    View Code

    B:给一个n*m的矩阵,一行一行从左到右编号依次加一直到n*m。有如下操作:

    1.交换x、y行。

    2.交换x、y列。

    3.询问某一个子矩阵的k次前缀和的和。

    n,m,q<=100000,k<=10。

    我们不可能直接维护整个矩阵,所以一定是把矩阵拆成两维分别维护。

    ​ 原来的第i行j列的值是$(i-1)*m+j$,我们可以把它理解成$a_i+b_j$。交换某一行或某一列时,相当于交换$a$或$b$中的两个元素。

    ​ 观察子矩阵中的每一个元素对于一个询问的贡献,可以发现每个格子的系数相当于从这个格子出发走$k+1$步到达右下角(即$(x_2,y_2)$)的方案数,每次可以走到两维坐标都大于等于它的一个格子(包括自己)。由此可知两维系数是独立的,对于一个格子$(i,j)$其系数可以写成$c_i*d_j$的形式,因为格子的两维坐标增大是互不影响的。而$c_i,d_i$就是在一维的坐标中,每次往右走若干步,走$k+1$次走到某一个端点的方案数。用插板法可得其为$inom{x+k}{k}$,其中$x$是到这个端点的距离。

    ​ 最终的答案是
    $$
    sum_{i=x1}^{x2}sum_{j=y1}^{y2}c_id_j(a_i+b_j)
    $$

    $$
    =(sum_{i=x1}^{x2}c_ia_i)(sum_{j=y1}^{y2}d_j)+(sum_{i=x1}^{x2}c_i)(sum_{j=y1}^{y2}d_jb_j)
    $$
    暴力计算这个式子,一个询问就可以$O(n+m)$求出答案。

    易得$c_i=inom{k+x_2-i}{k}=frac{(k+x_2-i)!}{k!(x2-i)!}=frac{1}{k!}(k+x_2-i)^{underline{k}}$

    我们知道
    $$
    x^{underline{n}}=sum_{i=0}^n(-1)^{n-i}s(n,i)x^i
    $$
    其中$s(n,i)$是第一类斯特林数

    将这个下降幂套进去
    $$
    (k+x_2-i)^{underline{k}}=sum_{d=0}^k(-1)^{k-d}s(k,d)(k+x_2-i)^d
    $$

    $$
    =sum_{d=0}^k(-1)^{k-d}s(k,d)sum_{e=0}^dinom{d}{e}(x_2+k)^e(-i)^{d-e}
    $$

    如果把$x_2,k$看成参数,这是一个关于$i$的$k$次多项式。

    我们只要对于0~10维护$sum a_i imes i^k$就好了(当然,有些细节不同,仍需推式子)。对于另一维同理。修改就是交换$a_x,a_y$。

    其实我们不需要推式子,我们只要知道系数是关于$i$的$k$次多项式,你可以暴力拆解所有的因式,就可以得到这些系数。

    $c_i=inom{k+x_2-i}{k}=frac{(k+x_2-i)!}{k!(x2-i)!}=frac{1}{k!}(k+x_2-i)^{underline{k}}$

    展开这个下降幂,可得

    $(k+x_2-i)^{underline{k}}=(k+x_2-i)(k+x_2-i-1)(k+x_2-i-2)...$

    将其看成关于$i$和$x_2$的二元多项式,对于每个k预处理一下这些多项式每一项的系数,询问时把$x_2$代进去。

    ​ 一次修改复杂度是$O(klogn)$的,询问是$O(k^2+klogn)$的


    C:有如下代码:

    void add_fish(long long &cnt, long long x, long long len) {
    	long long y = x % len;
    	while(h[y] != -1 && h[y] != x)
    		y = (y + 1) % len, cnt ++;
    	h[y] = x;
    }
    long long solve(long long len) {
    	for(int i = 0; i < len; i ++) h[i] = -1;
    	long long cnt = 0;
    	for(int i = 1; i <= n; i ++) add_fish(cnt, a[i], len);
    	return cnt;
    }
    

    现在给出数组a,问在long long范围内,solve的返回值最大为多少?

  • 相关阅读:
    浏览器返回错误汇总分析
    黄金投资品种众多 个人如何投资黄金
    .NET设计模式系列文章 (转自TerryLee's Tech Space)
    .NET设计模式(7):创建型模式专题总结(Creational Pattern)
    一个很经典的下拉式菜单(附效果)
    .NET设计模式(16):模版方法(Template Method)
    搜索引擎优化基础(转并整理添加)
    .NET设计模式(18):迭代器模式(Iterator Pattern)
    【ASP.NET】网页中嵌入视频的三种方法
    .NET设计模式(15):结构型模式专题总结
  • 原文地址:https://www.cnblogs.com/GreenDuck/p/12300758.html
Copyright © 2011-2022 走看看