• UOJ272 [清华集训2016] 石家庄的工人阶级队伍比较坚强 【分治乘法】


    题目分析:

    首先不难注意到式子就是异或卷积,所以考虑用分治乘法推出优化方法。
    我们把一个整体$f$拆成$f-,fpm,f+$,然后另一个拆成$g-,gpm,g+$.这样做的好处是能更清楚的分析问题。下面我们下宽油(大雾)。
    发现三个部分要求的式子是在两者相乘中选不同的三个,所以我们发现三个部分中每取一个有相同。这样我们聚焦到$--,-pm,-+$三个东西。观察二进制FWT,可以假想它们要使用到三次单位根。这样只需要把三个根错开排列就行了。
    做分治乘法的时候注意把虚部的$I$记做$sqrt{3}i$.

    代码:

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 
      4 const int maxn = 1020000;
      5 
      6 struct cn{int rl,vir;}e[3]; // vir's real meaning is vir*sqrt(3)
      7 
      8 int iv2,iv3;
      9 int m,n,t,p,phi;
     10 int b3[20],b[20][20];
     11 cn val[maxn],f[maxn];
     12 
     13 int W[maxn],L[maxn];
     14 
     15 cn operator +(const cn& alpha,const cn& beta){
     16     cn ans = (cn){alpha.rl+beta.rl,alpha.vir+beta.vir};
     17     if(ans.rl >= p) ans.rl -= p;
     18     if(ans.vir >= p) ans.vir -= p;
     19     return ans;
     20 }
     21 cn operator *(const cn& alpha,const cn& beta){
     22     cn ans = (cn){0,0};
     23     ans.rl = (1ll*alpha.rl*beta.rl-3ll*alpha.vir*beta.vir)%p;
     24     ans.rl += p; if(ans.rl >= p) ans.rl -= p;
     25     ans.vir = (1ll*alpha.vir*beta.rl+1ll*alpha.rl*beta.vir)%p;
     26     return ans;
     27 }
     28 cn operator *(const cn& alpha,const int& beta){
     29     cn ans=alpha;ans.rl=(1ll*ans.rl*beta)%p;ans.vir=(1ll*ans.vir*beta)%p;
     30     return ans;
     31 }
     32 
     33 cn fast_pow(cn now,int pw){
     34     int bit = 1;cn ans = (cn){1,0},dt = now;
     35     while(bit <= pw){
     36     if(bit & pw) ans = ans*dt;
     37     bit<<=1;dt = dt*dt;
     38     }
     39     return ans;
     40 }
     41 int fast_pow(int now,int pw){
     42     int bit = 1,ans = 1,dt = now;
     43     while(bit <= pw){
     44     if(bit & pw) ans = (1ll*ans*dt)%p;
     45     bit<<=1;dt = (1ll*dt*dt)%p;
     46     }
     47     return ans;
     48 }
     49 
     50 void read(){
     51     scanf("%d%d%d",&m,&t,&p);
     52     b3[0] = 1; for(int i=1;i<=m;i++) b3[i] = b3[i-1]*3;
     53     n = b3[m];
     54     for(int i=0;i<n;i++) scanf("%d",&f[i].rl);
     55     for(int i=0;i<=m;i++){
     56     for(int j=0;i+j<=m;j++){
     57         scanf("%d",&b[i][j]);
     58     }
     59     }
     60     val[0].rl = b[0][0];
     61     for(int i=1;i<n;i++){
     62     W[i] = W[i/3],L[i] = L[i/3];
     63     if(i % 3 == 2) L[i]++;
     64     if(i % 3 == 1) W[i]++;
     65     val[i].rl = b[W[i]][L[i]];
     66     }
     67 }
     68 
     69 void multi(int l,int r){
     70     if(l == r-1){
     71     f[l] = f[l]*fast_pow(val[l],t);
     72     }else{
     73     int l1 = l+(r-l)/3,l2 = l+2*(r-l)/3,d = l2-l1;
     74     for(int i=0;i<d;i++){
     75         cn p1 = f[l+i],p2 = f[l1+i],p3 = f[l2+i];
     76         f[l+i] = p1+p2+p3;
     77         f[l1+i] = p1+e[1]*p2+e[2]*p3;f[l2+i] = p1+e[2]*p2+e[1]*p3;
     78         p1 = val[l+i],p2 = val[l1+i],p3 = val[l2+i];
     79         val[l+i] = p1+p2+p3;
     80         val[l1+i] = p1+e[1]*p2+e[2]*p3;val[l2+i] = p1+e[2]*p2+e[1]*p3;
     81     }
     82     multi(l,l1); multi(l1,l2); multi(l2,r);
     83     for(int i=0;i<d;i++){
     84         cn p1 = f[l+i],p2 = f[l1+i],p3 = f[l2+i];
     85         f[l+i] = p1+p2+p3;
     86         f[l1+i] = p1+e[2]*p2+e[1]*p3;f[l2+i] = p1+e[1]*p2+e[2]*p3;
     87         f[l+i]=f[l+i]*iv3;f[l1+i]=f[l1+i]*iv3;f[l2+i]=f[l2+i]*iv3;
     88     }
     89     }
     90 }
     91 
     92 void init(){
     93     phi = p;int z = p;
     94     for(int i=2;i*i<=p;i++){
     95     if(p % i == 0){
     96         while(p%i == 0) p /= i;
     97         phi = (phi/i)*(i-1);
     98     }
     99     }
    100     if(p != 1) phi = (phi/p)*(p-1); p =z;
    101     iv2 = fast_pow(2,phi-1); iv3 = fast_pow(3,phi-1);
    102     e[0] = (cn){1,0}; e[1] = (cn){p-iv2,iv2}; e[2] = (cn){p-iv2,p-iv2};
    103 }
    104 
    105 void work(){
    106     multi(0,n);//[0,n)
    107     for(int i=0;i<n;i++) printf("%d
    ",f[i].rl);
    108 }
    109 
    110 int main(){
    111     read();
    112     init();
    113     work();
    114     return 0;
    115 }
  • 相关阅读:
    Thread.join()的使用
    Java 编程思想
    LoadRunner 常见错误
    Selenium+IDEA+Maven+TestNG环境搭建
    计算机基本知识了解(二)
    Java中int和Integer的区别
    计算机基本知识了解(一)
    Jmeter安装及环境配置
    app稳定性测试-monkey测试
    .net framework
  • 原文地址:https://www.cnblogs.com/Menhera/p/9458446.html
Copyright © 2020-2023  润新知