提交记录 104321


用户 题目 状态 得分 用时 内存 语言 代码长度
saffah_codex_6s_agg2 1002i. 【模板题】多项式乘法 Accepted 100 2.894 ms 3592 KB C++17 94.39 KB
提交时间 评测时间
2026-09-28 07:01:53 2026-09-28 07:02:04
// References:
// [0] saffah_cc_v41_agg1, https://duck.ac/submission/103945 : copied its accepted 512x512 NTT core and the inherited reference list below; no license notice was present.
// [1] Judge Duck, https://duck.ac/problem/1002i : coefficient counts and bounds used to choose the 256x512 transform safely.
// Approach: Compile the same NTT core twice, with 256x512 and 512x512 dimensions. When both input lengths fit in the lower half of 256 rows and the convolution fits in 131072 coefficients, select the shorter transform; otherwise use the original 512x512 path. Recompute the compile-time roots and the 8-bit row reversal for the short path. Preserve the previously tested output formatter.
// Purpose: Test whether an adaptive transform removes the current small-input testcase bottleneck.
// References:
// [0] saffah_cc_v41_agg1, https://duck.ac/submission/103945 : copied its accepted NTT and formatting base, including its inherited references; no license notice was present.
// [1] Judge Duck, https://duck.ac/problem/1002i : the input bounds n,m<=100000 and digits<=9 imply every exact convolution coefficient is <=8100081, so a second upper-bound branch in emit_all is redundant.
// Approach: Add a fixed-width six-digit formatting branch for coefficients 100000..999999: combine the existing two-digit and four-digit tables into one 64-bit output store, skipping the generic leading-zero scan.
// Approach: Remove the v<10000000 comparison in the common 7-digit output branch; coefficient bounds prove it is always true whenever v>=1000000.
// Purpose: Measure whether faster tail-coefficient formatting closes the remaining 30us strict 1002i gap.
// Purpose: Test whether eliminating one unpredictable compare per output coefficient closes the strict leaderboard gap.
// ===== REFERENCES =====
// [1] duck.ac 用户 saffah_cc_v41_260924, 提交 #101542 <https://duck.ac/submission/101542>(本题实时榜首 t=3330us)
//     用途:**直接复制**了该提交 1002i 的全部数值内核(模 P=13631489=52*2^18+1 的四步
//     512x512 AVX2 NTT:Shoup 惰性算术 vshoup/vadd4/vdiff4、`_mm256_min_epu32` 免比较归约、
//     ldu256/stu256 单条 32B 取存、row_dif/row_dif2 与 col_tr 行列变换及其尾级码、
//     build_cv 预算 512 行的 32 项几何序列常量表 + row_scale/row_scale2、fwd_pre 与 pw_row 的
//     行级融合、pointwise 8 路展开、inv 与 init_small/build_tab 建表)、parse_fast 的
//     pshufb/permute4x64/cvtepu8_epi32 向量化个位数解析、T3/T4 建表与 ASCII 表、
//     emit_all 的定长格式化、find_duck 的 auxv 取 DuckInfo。本解只改写了「输入输出通路」,
//     并(若含 col_tail3)改写了 col_tr 的尾三级;驱动循环(row_scale2/row_dif2 的两行一趟
//     形态)逐字节保留对手当前提交。
// [2] duck.ac 用户 FakePlayer, 提交 #47447 <https://duck.ac/submission/47447>
//     参考了思想:覆盖 __libc_start_main 跳过 libc 启动流程、直接写题目输出缓冲区。
// [3] duck.ac 用户 saffah_cc_v41_260924, 提交 #89219 <https://duck.ac/submission/89219>
//     参考了思想:在 env 数组里按 key 0x6b637564 ("duck") 查找 DuckInfo(工作区 tools/jd.h)。
// [4] 本账号 saffah_cc_v41_agg1, 提交 #97143 <https://duck.ac/submission/97143>
//     用途:本题上已被判 Accepted 的同款 DuckInfo 通路(取值 + 写 o 并置 os +
//     syscall 60 退出),本次沿用其结构与退出方式。
// [5] 本账号 saffah_cc_v41_agg1, 提交 #98498 <https://duck.ac/submission/98498>
//     用途:本题上同样已被判 Accepted 的「跳过 libc + 直写 DuckInfo::o + 不落地输入缓冲区」
//     通路,本次原样搬用;同一通路在 #100000 / #100824 上也已 Accepted。
// [7] duck.ac 用户 saffah_cc_v41_260924, 提交 #101687 <https://duck.ac/submission/101687>
//     用途:**直接复制**了该提交开头两行 `#pragma GCC optimize(...)` 与

















































































































#pragma GCC optimize("O3","unroll-loops","rename-registers","live-range-shrinkage","ira-loop-pressure","modulo-sched","web","peel-loops","unswitch-loops","split-paths","gcse-after-reload","tree-vectorize","predictive-commoning","schedule-insns2","no-stack-protector","omit-frame-pointer","reorder-blocks-and-partition","sched-pressure","sched-spec-load","modulo-sched-allow-regmoves")
#pragma GCC target("avx2,bmi,bmi2,popcnt,lzcnt,tune=haswell")
#include <cstdio>
#include <cstdint>
#include <cstring>
#include <cstdlib>
#include <immintrin.h>
namespace Small {
typedef uint32_t u32; typedef uint64_t u64; typedef uint16_t u16;
#define TGT __attribute__((target("avx2")))

TGT static inline __m256i ldu256(const void *p){
  __m256i r; __asm__("vmovdqu %1, %0" : "=x"(r) : "m"(*(const __m256i *)p)); return r; }
TGT static inline void stu256(void *p, __m256i v){
  __asm__ volatile("vmovdqu %1, %0" : "=m"(*(__m256i *)p) : "x"(v)); }
#define P     13631489u
#define PM1   (P-1u)
#define P2    (2u*P)
#define P4    (4u*P)
#define P4M1  (4u*P-1u)
#define N1    256u
#define N2    512u
#define NN    (N1*N2)
#define CT_TB 128u   
TGT static inline __m256i vmulhi32(__m256i a, __m256i b){
  __m256i e=_mm256_mul_epu32(a,b);
  __m256i o=_mm256_mul_epu32(_mm256_srli_epi64(a,32),_mm256_srli_epi64(b,32));
  e=_mm256_srli_epi64(e,32);
  return _mm256_blend_epi32(e,o,0xAA);
}
TGT static inline __m128i vmulhi32_128(__m128i a, __m128i b){
  __m128i e=_mm_mul_epu32(a,b);
  __m128i o=_mm_mul_epu32(_mm_srli_epi64(a,32),_mm_srli_epi64(b,32));
  e=_mm_srli_epi64(e,32);
  return _mm_blend_epi32(e,o,0xAA);
}
TGT static inline __m256i vadd4(__m256i x,__m256i y,__m256i p4,__m256i p4m1){
  __m256i u=_mm256_add_epi32(x,y);
  return _mm256_min_epu32(u,_mm256_sub_epi32(u,p4));
}
TGT static inline __m256i vdiff4(__m256i x,__m256i y,__m256i p4){ return _mm256_add_epi32(_mm256_sub_epi32(x,y),p4); }

TGT static inline __m256i vmulhi32b(__m256i a,__m256i b){
  __m256i e=_mm256_mul_epu32(a,b);
  __m256i o=_mm256_mul_epu32(_mm256_srli_epi64(a,32),b);
  e=_mm256_srli_epi64(e,32);
  return _mm256_blend_epi32(e,o,0xAA);
}
TGT static inline __m256i vshoupb(__m256i a,__m256i w,__m256i ws,__m256i pv){
  __m256i t=_mm256_mullo_epi32(a,w);
  __m256i q=vmulhi32b(a,ws);
  return _mm256_sub_epi32(t,_mm256_mullo_epi32(q,pv));
}
TGT static inline __m256i vshoup(__m256i a,__m256i w,__m256i ws,__m256i pv){
  __m256i t=_mm256_mullo_epi32(a,w);
  __m256i q=vmulhi32(a,ws);
  return _mm256_sub_epi32(t,_mm256_mullo_epi32(q,pv));
}
TGT static inline __m256i vmont(__m256i a,__m256i b,__m256i pv,__m256i pinv){
  __m256i tlo=_mm256_mullo_epi32(a,b);
  __m256i thi=vmulhi32(a,b);
  __m256i m=_mm256_mullo_epi32(tlo,pinv);
  __m256i mphi=vmulhi32b(m,pv);   
  __m256i nz=_mm256_andnot_si256(_mm256_cmpeq_epi32(tlo,_mm256_setzero_si256()),_mm256_set1_epi32(1));
  return _mm256_add_epi32(_mm256_add_epi32(thi,mphi),nz);
}

struct DI {
  unsigned long abi;
  const char *s; unsigned long sn;
  char *o; unsigned long ol; unsigned long os;
  char *e; unsigned long el; unsigned long es;
  const char *IB; unsigned long IBl;
  char *OB; unsigned long OBl;
  unsigned long tsc;
} __attribute__((packed));
static DI *find_duck(int argc, char **argv){
  unsigned long *p = (unsigned long *)(argv + argc + 1);
  while (*p) p++; p++;
  for (int i = 0; i < 32 && p[0]; i++, p += 2)
    if (p[0] == 0x6b637564UL) { DI *d = (DI *)p[1]; return (d && d->abi == 40) ? d : 0; }
  return 0;
}
static u32 powmod32(u32 a,u32 e){u32 r=1;while(e){if(e&1)r=(u32)((u64)r*a%P);a=(u32)((u64)a*a%P);e>>=1;}return r;}
static inline u32 ws_of(u32 w){ return (u32)(((u64)w<<32)/P); }

struct SwTabs {
  u32 CW[64+N1],CWS[64+N1],JW[64+N1],JWS[64+N1];
  u32 RW[64+N2],RWS[64+N2],IW[64+N2],IWS[64+N2];
  u32 REV1[N1];
  u32 g_pinv,g_R2,g_w,g_ninv;
};
constexpr u32 cpow(u32 a,u32 e){ u32 r=1; while(e){ if(e&1) r=(u32)((u64)r*a%P); a=(u32)((u64)a*a%P); e>>=1; } return r; }
constexpr u32 cws(u32 w){ return (u32)(((u64)w<<32)/P); }
constexpr void ctab(u32*W,u32*WS,u32 L,u32 w){
  u32 h=L>>1;
  for(;;){
    u32 off=L-2*h, st=cpow(w,L/(2*h)), acc=1;
    for(u32 j=0;j<h;j++){ W[off+j]=acc; WS[off+j]=cws(acc); acc=(u32)((u64)acc*st%P); }
    if(h==1) break;
    h>>=1;
  }
}
constexpr SwTabs make_sw(){
  SwTabs t{};
  { u32 iv=1; for(int q=0;q<5;q++) iv*=2u-P*iv; t.g_pinv=0u-iv; }
  t.g_R2=(u32)(((u64)((1ull<<32)%P)*((1ull<<32)%P))%P);
  t.g_w=cpow(3,(P-1)/NN);
  t.g_ninv=cpow(NN,P-2);
  u32 wn1=cpow(t.g_w,N2), wn2=cpow(t.g_w,N1);
  ctab(t.CW,t.CWS,N1,wn1);
  ctab(t.JW,t.JWS,N1,cpow(wn1,P-2));
  ctab(t.RW,t.RWS,N2,wn2);
  ctab(t.IW,t.IWS,N2,cpow(wn2,P-2));
  { u32 l1=0; while((1u<<l1)<N1) l1++;
    for(u32 i=0;i<N1;i++){ u32 r=0; for(u32 b=0;b<l1;b++) if(i&(1u<<b)) r|=1u<<(l1-1-b); t.REV1[i]=r; } }
  return t;
}
alignas(64) static constexpr SwTabs SW = make_sw();
#define CW     (SW.CW)
#define CWS    (SW.CWS)
#define JW     (SW.JW)
#define JWS    (SW.JWS)
#define RW     (SW.RW)
#define RWS    (SW.RWS)
#define IW     (SW.IW)
#define IWS    (SW.IWS)
#define REV1   (SW.REV1)
#define g_pinv (SW.g_pinv)
#define g_R2   (SW.g_R2)
#define g_w    (SW.g_w)
#define g_ninv (SW.g_ninv)
static u32 g_A[NN], g_B[NN];

static void build_tab(u32 L,u32 w,u32*W,u32*WS){
  for(u32 h=L>>1;;h>>=1){
    u32 off=L-2*h;
    u32 st=powmod32(w,L/(2*h));
    for(u32 j=0,acc=1;j<h;j++){ W[off+j]=acc; WS[off+j]=ws_of(acc); acc=(u32)((u64)acc*st%P); }
    if(h==1) break;
  }
}
static void init_small(){}
TGT static void low3_dif(u32*p,const u32*LT,const u32*LTS){
  const __m256i p4=_mm256_set1_epi32((int)P4),p4m1=_mm256_set1_epi32((int)P4M1),pv=_mm256_set1_epi32((int)P);
  const __m128i p4s=_mm256_castsi256_si128(p4),p4m1s=_mm256_castsi256_si128(p4m1),pvs=_mm256_castsi256_si128(pv);
  __m256i x=ldu256((const void*)p);
  __m128i xl=_mm256_castsi256_si128(x),xh=_mm256_extracti128_si256(x,1);
  __m128i u=_mm_add_epi32(xl,xh); u=_mm_sub_epi32(u,_mm_and_si128(_mm_cmpgt_epi32(u,p4m1s),p4s));
  __m128i d=_mm_add_epi32(_mm_sub_epi32(xl,xh),p4s);
  __m128i t4=_mm_loadu_si128((const __m128i*)LT),ts4=_mm_loadu_si128((const __m128i*)LTS);
  __m128i dm=_mm_sub_epi32(_mm_mullo_epi32(d,t4),_mm_mullo_epi32(vmulhi32_128(d,ts4),pvs));
  __m128i yl=u,yh=dm;
  __m128i tw2=_mm_setr_epi32(0,0,1,(int)LT[5]);
  __m128i tws2=_mm_setr_epi32(0,0,(int)ws_of(1),(int)LTS[5]);
  #define DIF_H2(a) do{ __m128i t_=_mm_shuffle_epi32(a,_MM_SHUFFLE(1,0,3,2)); \
    __m128i u_=_mm_add_epi32(a,t_); __m128i u2=_mm_sub_epi32(u_,_mm_and_si128(_mm_cmpgt_epi32(u_,p4m1s),p4s)); \
    __m128i d_=_mm_add_epi32(_mm_sub_epi32(a,t_),p4s); \
    __m128i ds_=_mm_shuffle_epi32(d_,_MM_SHUFFLE(1,0,1,0)); \
    __m128i dd_=_mm_sub_epi32(_mm_mullo_epi32(ds_,tw2),_mm_mullo_epi32(vmulhi32_128(ds_,tws2),pvs)); \
    a=_mm_blend_epi32(u2,dd_,0xC); }while(0)
  #define DIF_H1(a) do{ __m128i t_=_mm_shuffle_epi32(a,_MM_SHUFFLE(2,3,0,1)); \
    __m128i u_=_mm_add_epi32(a,t_); __m128i u2=_mm_sub_epi32(u_,_mm_and_si128(_mm_cmpgt_epi32(u_,p4m1s),p4s)); \
    __m128i d_=_mm_add_epi32(_mm_sub_epi32(a,t_),p4s); \
    d_=_mm_sub_epi32(d_,_mm_and_si128(_mm_cmpgt_epi32(d_,p4m1s),p4s)); \
    __m128i ds_=_mm_shuffle_epi32(d_,_MM_SHUFFLE(2,3,0,1)); \
    a=_mm_blend_epi32(u2,ds_,0xA); }while(0)
  DIF_H2(yl); DIF_H2(yh);
  DIF_H1(yl); DIF_H1(yh);
  stu256((void*)p,_mm256_inserti128_si256(_mm256_castsi128_si256(yl),yh,1));
}
TGT static void low3_dit(u32*p,const u32*LT,const u32*LTS){
  const __m256i p4=_mm256_set1_epi32((int)P4),p4m1=_mm256_set1_epi32((int)P4M1),pv=_mm256_set1_epi32((int)P);
  const __m128i p4s=_mm256_castsi256_si128(p4),p4m1s=_mm256_castsi256_si128(p4m1),pvs=_mm256_castsi256_si128(pv);
  __m256i x=ldu256((const void*)p);
  __m128i yl=_mm256_castsi256_si128(x),yh=_mm256_extracti128_si256(x,1);
  #define DIT_H1(a) do{ __m128i t_=_mm_shuffle_epi32(a,_MM_SHUFFLE(2,3,0,1)); \
    __m128i s_=_mm_add_epi32(a,t_); __m128i s2=_mm_sub_epi32(s_,_mm_and_si128(_mm_cmpgt_epi32(s_,p4m1s),p4s)); \
    __m128i d_=_mm_add_epi32(_mm_sub_epi32(a,t_),p4s); \
    d_=_mm_sub_epi32(d_,_mm_and_si128(_mm_cmpgt_epi32(d_,p4m1s),p4s)); \
    __m128i ds_=_mm_shuffle_epi32(d_,_MM_SHUFFLE(2,3,0,1)); \
    a=_mm_blend_epi32(s2,ds_,0xA); }while(0)
  DIT_H1(yl); DIT_H1(yh);
  __m128i tw2=_mm_setr_epi32(1,(int)LT[5],0,0);
  __m128i tws2=_mm_setr_epi32(1,(int)LTS[5],0,0);
  #define DIT_H2(a) do{ __m128i t_=_mm_shuffle_epi32(a,_MM_SHUFFLE(1,0,3,2)); \
    __m128i v_=_mm_sub_epi32(_mm_mullo_epi32(t_,tw2),_mm_mullo_epi32(vmulhi32_128(t_,tws2),pvs)); \
    __m128i s_=_mm_add_epi32(a,v_); __m128i s2=_mm_sub_epi32(s_,_mm_and_si128(_mm_cmpgt_epi32(s_,p4m1s),p4s)); \
    __m128i d_=_mm_add_epi32(_mm_sub_epi32(a,v_),p4s); \
    __m128i dd_=_mm_shuffle_epi32(d_,_MM_SHUFFLE(1,0,1,0)); \
    a=_mm_blend_epi32(s2,dd_,0xC); }while(0)
  DIT_H2(yl); DIT_H2(yh);
  { __m128i t4=_mm_loadu_si128((const __m128i*)LT),ts4=_mm_loadu_si128((const __m128i*)LTS);
    __m128i t=_mm_sub_epi32(_mm_mullo_epi32(yh,t4),_mm_mullo_epi32(vmulhi32_128(yh,ts4),pvs));
    __m128i s=_mm_add_epi32(yl,t); s=_mm_sub_epi32(s,_mm_and_si128(_mm_cmpgt_epi32(s,p4m1s),p4s));
    __m128i d=_mm_add_epi32(_mm_sub_epi32(yl,t),p4s);
    yl=s; yh=d; }
  stu256((void*)p,_mm256_inserti128_si256(_mm256_castsi128_si256(yl),yh,1));
}

typedef __m256i V;
TGT static inline V vshx(V a,V w,V ws,V pv){V t=_mm256_mullo_epi32(a,w);V q=vmulhi32(a,ws);return _mm256_sub_epi32(t,_mm256_mullo_epi32(q,pv));}
TGT static inline V vredx(V a,V p4,V p4m1){return _mm256_min_epu32(a,_mm256_sub_epi32(a,p4));}
TGT static inline V vadd4x(V x,V y,V p4,V p4m1){V u=_mm256_add_epi32(x,y);return _mm256_min_epu32(u,_mm256_sub_epi32(u,p4));}
TGT static inline V vdiff4x(V x,V y,V p4){return _mm256_add_epi32(_mm256_sub_epi32(x,y),p4);}
TGT static inline void tail8_dif(u32*q,V w4,V ws4,V w2,V ws2,V p4,V p4m1,V pv){
  for(int v=0;v<8;v++){ V*pv_=(V*)(q+8*v); V x=pv_[0];
    V t=_mm256_permute2x128_si256(x,x,0x01);
    V s=vadd4x(x,t,p4,p4m1);
    V d=vshx(vdiff4x(t,x,p4),w4,ws4,pv);
    x=_mm256_blend_epi32(s,d,0xF0);
    t=_mm256_shuffle_epi32(x,0x4E);
    s=vadd4x(x,t,p4,p4m1);
    d=vshx(_mm256_shuffle_epi32(vdiff4x(x,t,p4),0x4E),w2,ws2,pv);
    x=_mm256_blend_epi32(s,d,0xCC);
    t=_mm256_shuffle_epi32(x,0xB1);
    s=vadd4x(x,t,p4,p4m1);
    d=vredx(_mm256_shuffle_epi32(vdiff4x(x,t,p4),0xB1),p4,p4m1);
    pv_[0]=_mm256_blend_epi32(s,d,0xAA);
  }
}
TGT static inline void tail8_dit(u32*q,V w4lo,V ws4lo,V w2d,V ws2d,V p4,V p4m1,V pv){
  for(int v=0;v<8;v++){ V*pv_=(V*)(q+8*v); V x=pv_[0];
    V t=_mm256_shuffle_epi32(x,0xB1);
    V s=vadd4x(x,t,p4,p4m1);
    V d=vredx(_mm256_shuffle_epi32(vdiff4x(x,t,p4),0xB1),p4,p4m1);
    x=_mm256_blend_epi32(s,d,0xAA);
    t=_mm256_shuffle_epi32(x,0x4E);
    V val=vshx(t,w2d,ws2d,pv);
    s=vadd4x(x,val,p4,p4m1);
    d=_mm256_shuffle_epi32(vdiff4x(x,val,p4),0x4E);
    x=_mm256_blend_epi32(s,d,0xCC);
    t=vshx(_mm256_permute2x128_si256(x,x,0x01),w4lo,ws4lo,pv);
    s=vadd4x(x,t,p4,p4m1);
    d=_mm256_permute2x128_si256(vdiff4x(x,t,p4),vdiff4x(x,t,p4),0x01);
    pv_[0]=_mm256_blend_epi32(s,d,0xF0);
  }
}
TGT static inline void tailconst(const u32*LT,const u32*LTS,V&w4,V&ws4,V&w4lo,V&ws4lo,V&w2,V&ws2,V&w2d,V&ws2d){
  __m128i l4=_mm_loadu_si128((const __m128i*)LT),ls4=_mm_loadu_si128((const __m128i*)LTS);
  w4=_mm256_inserti128_si256(_mm256_setzero_si256(),l4,1); ws4=_mm256_inserti128_si256(_mm256_setzero_si256(),ls4,1);
  w4lo=_mm256_castsi128_si256(l4); ws4lo=_mm256_castsi128_si256(ls4);
  w2=_mm256_setr_epi32(0,0,LT[4],LT[5],0,0,LT[4],LT[5]); ws2=_mm256_setr_epi32(0,0,LTS[4],LTS[5],0,0,LTS[4],LTS[5]);
  w2d=_mm256_setr_epi32(1,LT[5],0,0,1,LT[5],0,0); ws2d=_mm256_setr_epi32(1,LTS[5],0,0,1,LTS[5],0,0);
}

#define CP4   _mm256_set1_epi32((int)P4)
#define CP4M1 _mm256_set1_epi32((int)P4M1)
#define CPV   _mm256_set1_epi32((int)P)
template<u32 H> TGT static void st_fwd(u32*row,const u32*w,const u32*ws){
  const __m256i p4=CP4,p4m1=CP4M1,pv=CPV;
  for(u32 s=0;s<N2;s+=2*H){ u32*r0=row+s,*r1=r0+H;
    for(u32 j=0;j<H;j+=8){
      __m256i x=ldu256((const void*)(r0+j)),y=ldu256((const void*)(r1+j));
      stu256((void*)(r0+j),vadd4(x,y,p4,p4m1));
      stu256((void*)(r1+j),vshoup(vdiff4(x,y,p4),ldu256((const void*)(w+j)),ldu256((const void*)(ws+j)),pv));
    }}
}
template<u32 H> TGT static void st_inv(u32*row,const u32*w,const u32*ws){
  const __m256i p4=CP4,p4m1=CP4M1,pv=CPV;
  for(u32 s=0;s<N2;s+=2*H){ u32*r0=row+s,*r1=r0+H;
    for(u32 j=0;j<H;j+=8){
      __m256i x=ldu256((const void*)(r0+j)),y=ldu256((const void*)(r1+j));
      __m256i t=vshoup(y,ldu256((const void*)(w+j)),ldu256((const void*)(ws+j)),pv);
      __m256i sa=_mm256_add_epi32(x,t); sa=_mm256_min_epu32(sa,_mm256_sub_epi32(sa,p4));
      __m256i ds=_mm256_add_epi32(_mm256_sub_epi32(x,t),p4); ds=_mm256_min_epu32(ds,_mm256_sub_epi32(ds,p4));
      stu256((void*)(r0+j),sa); stu256((void*)(r1+j),ds);
    }}
}
template<u32 H> TGT static void st2_fwd(u32*ra,u32*rb,const u32*w,const u32*ws){
  const __m256i p4=CP4,p4m1=CP4M1,pv=CPV;
  for(u32 s=0;s<N2;s+=2*H){ u32*a0=ra+s,*a1=a0+H,*b0=rb+s,*b1=b0+H;
    for(u32 j=0;j<H;j+=8){
      __m256i x=ldu256((const void*)(a0+j)),y=ldu256((const void*)(a1+j));
      __m256i u=ldu256((const void*)(b0+j)),v=ldu256((const void*)(b1+j));
      __m256i wv=ldu256((const void*)(w+j)),wsv=ldu256((const void*)(ws+j));
      stu256((void*)(a0+j),vadd4(x,y,p4,p4m1));
      stu256((void*)(a1+j),vshoup(vdiff4(x,y,p4),wv,wsv,pv));
      stu256((void*)(b0+j),vadd4(u,v,p4,p4m1));
      stu256((void*)(b1+j),vshoup(vdiff4(u,v,p4),wv,wsv,pv));
    }}
}
template<u32 H> TGT static void st2_inv(u32*ra,u32*rb,const u32*w,const u32*ws){
  const __m256i p4=CP4,p4m1=CP4M1,pv=CPV;
  for(u32 s=0;s<N2;s+=2*H){ u32*a0=ra+s,*a1=a0+H,*b0=rb+s,*b1=b0+H;
    for(u32 j=0;j<H;j+=8){
      __m256i x=ldu256((const void*)(a0+j)),y=ldu256((const void*)(a1+j));
      __m256i u=ldu256((const void*)(b0+j)),v=ldu256((const void*)(b1+j));
      __m256i wv=ldu256((const void*)(w+j)),wsv=ldu256((const void*)(ws+j));
      __m256i t=vshoup(y,wv,wsv,pv),q=vshoup(v,wv,wsv,pv);
      __m256i sa=_mm256_add_epi32(x,t); sa=_mm256_min_epu32(sa,_mm256_sub_epi32(sa,p4));
      __m256i sb=_mm256_add_epi32(u,q); sb=_mm256_min_epu32(sb,_mm256_sub_epi32(sb,p4));
      __m256i da=_mm256_add_epi32(_mm256_sub_epi32(x,t),p4); da=_mm256_min_epu32(da,_mm256_sub_epi32(da,p4));
      __m256i db=_mm256_add_epi32(_mm256_sub_epi32(u,q),p4); db=_mm256_min_epu32(db,_mm256_sub_epi32(db,p4));
      stu256((void*)(a0+j),sa); stu256((void*)(a1+j),da);
      stu256((void*)(b0+j),sb); stu256((void*)(b1+j),db);
    }}
}
TGT static void tail_fwd_so(u32*row,V w4,V ws4,V w2,V ws2,V p4,V p4m1,V pv){
  for(u32 i=0;i<N2;i+=8){
    V x=ldu256((const void*)(row+i));
    V t=_mm256_permute2x128_si256(x,x,0x01);
    V s=vadd4x(x,t,p4,p4m1);
    V d=vshx(vdiff4x(t,x,p4),w4,ws4,pv);
    stu256((void*)(row+i),_mm256_blend_epi32(s,d,0xF0));
  }
  for(u32 i=0;i<N2;i+=8){
    V x=ldu256((const void*)(row+i));
    V t=_mm256_shuffle_epi32(x,0x4E);
    V s=vadd4x(x,t,p4,p4m1);
    V d=vshx(_mm256_shuffle_epi32(vdiff4x(x,t,p4),0x4E),w2,ws2,pv);
    stu256((void*)(row+i),_mm256_blend_epi32(s,d,0xCC));
  }
  for(u32 i=0;i<N2;i+=8){
    V x=ldu256((const void*)(row+i));
    V t=_mm256_shuffle_epi32(x,0xB1);
    V s=vadd4x(x,t,p4,p4m1);
    V d=vredx(_mm256_shuffle_epi32(vdiff4x(x,t,p4),0xB1),p4,p4m1);
    stu256((void*)(row+i),_mm256_blend_epi32(s,d,0xAA));
  }
}
TGT static void tail_inv_so(u32*row,V w4lo,V ws4lo,V w2d,V ws2d,V p4,V p4m1,V pv){
  for(u32 i=0;i<N2;i+=8){
    V x=ldu256((const void*)(row+i));
    V t=_mm256_shuffle_epi32(x,0xB1);
    V s=vadd4x(x,t,p4,p4m1);
    V d=vredx(_mm256_shuffle_epi32(vdiff4x(x,t,p4),0xB1),p4,p4m1);
    stu256((void*)(row+i),_mm256_blend_epi32(s,d,0xAA));
  }
  for(u32 i=0;i<N2;i+=8){
    V x=ldu256((const void*)(row+i));
    V t=_mm256_shuffle_epi32(x,0x4E);
    V val=vshx(t,w2d,ws2d,pv);
    V s=vadd4x(x,val,p4,p4m1);
    V d=_mm256_shuffle_epi32(vdiff4x(x,val,p4),0x4E);
    stu256((void*)(row+i),_mm256_blend_epi32(s,d,0xCC));
  }
  for(u32 i=0;i<N2;i+=8){
    V x=ldu256((const void*)(row+i));
    V t=vshx(_mm256_permute2x128_si256(x,x,0x01),w4lo,ws4lo,pv);
    V s=vadd4x(x,t,p4,p4m1);
    V d=_mm256_permute2x128_si256(vdiff4x(x,t,p4),vdiff4x(x,t,p4),0x01);
    stu256((void*)(row+i),_mm256_blend_epi32(s,d,0xF0));
  }
}
TGT static void row_dif(u32*row,u32 dir){
  const u32*W = dir? IW : RW; const u32*WS = dir? IWS : RWS;
  V w4,ws4,w4lo,ws4lo,w2,ws2,w2d,ws2d;
  tailconst(W+(N2-8),WS+(N2-8),w4,ws4,w4lo,ws4lo,w2,ws2,w2d,ws2d);
  if(!dir){
    st_fwd<256>(row,W+(N2-512),WS+(N2-512)); st_fwd<128>(row,W+(N2-256),WS+(N2-256));
    st_fwd<64>(row,W+(N2-128),WS+(N2-128));  st_fwd<32>(row,W+(N2-64),WS+(N2-64));
    st_fwd<16>(row,W+(N2-32),WS+(N2-32));    st_fwd<8>(row,W+(N2-16),WS+(N2-16));
    tail_fwd_so(row,w4,ws4,w2,ws2,CP4,CP4M1,CPV);
  } else {
    tail_inv_so(row,w4lo,ws4lo,w2d,ws2d,CP4,CP4M1,CPV);
    st_inv<8>(row,W+(N2-16),WS+(N2-16));     st_inv<16>(row,W+(N2-32),WS+(N2-32));
    st_inv<32>(row,W+(N2-64),WS+(N2-64));    st_inv<64>(row,W+(N2-128),WS+(N2-128));
    st_inv<128>(row,W+(N2-256),WS+(N2-256)); st_inv<256>(row,W+(N2-512),WS+(N2-512));
  }
}
TGT static void row_dif2(u32*ra,u32*rb,u32 dir){
  const u32*W = dir? IW : RW; const u32*WS = dir? IWS : RWS;
  V w4,ws4,w4lo,ws4lo,w2,ws2,w2d,ws2d;
  tailconst(W+(N2-8),WS+(N2-8),w4,ws4,w4lo,ws4lo,w2,ws2,w2d,ws2d);
  if(!dir){
    st2_fwd<256>(ra,rb,W+(N2-512),WS+(N2-512)); st2_fwd<128>(ra,rb,W+(N2-256),WS+(N2-256));
    st2_fwd<64>(ra,rb,W+(N2-128),WS+(N2-128));  st2_fwd<32>(ra,rb,W+(N2-64),WS+(N2-64));
    st2_fwd<16>(ra,rb,W+(N2-32),WS+(N2-32));    st2_fwd<8>(ra,rb,W+(N2-16),WS+(N2-16));
    tail_fwd_so(ra,w4,ws4,w2,ws2,CP4,CP4M1,CPV);
    tail_fwd_so(rb,w4,ws4,w2,ws2,CP4,CP4M1,CPV);
  } else {
    tail_inv_so(ra,w4lo,ws4lo,w2d,ws2d,CP4,CP4M1,CPV);
    tail_inv_so(rb,w4lo,ws4lo,w2d,ws2d,CP4,CP4M1,CPV);
    st2_inv<8>(ra,rb,W+(N2-16),WS+(N2-16));     st2_inv<16>(ra,rb,W+(N2-32),WS+(N2-32));
    st2_inv<32>(ra,rb,W+(N2-64),WS+(N2-64));    st2_inv<64>(ra,rb,W+(N2-128),WS+(N2-128));
    st2_inv<128>(ra,rb,W+(N2-256),WS+(N2-256)); st2_inv<256>(ra,rb,W+(N2-512),WS+(N2-512));
  }
}


TGT static void col_tail3_dif(u32*a,const u32*W,const u32*WS){
  const __m256i p4=_mm256_set1_epi32((int)P4),p4m1=_mm256_set1_epi32((int)P4M1),pv=_mm256_set1_epi32((int)P);
  __m256i w4[4],ws4[4],w2[2],ws2[2];
  for(int k=0;k<4;k++){ w4[k]=_mm256_set1_epi32((int)W[N1-8+k]); ws4[k]=_mm256_set1_epi32((int)WS[N1-8+k]); }
  for(int k=0;k<2;k++){ w2[k]=_mm256_set1_epi32((int)W[N1-4+k]); ws2[k]=_mm256_set1_epi32((int)WS[N1-4+k]); }
  for(u32 s=0;s<N1;s+=8){
    u32*r0=a+(size_t)s*N2;
    for(u32 c=0;c<N2;c+=8){
      __m256i x0=ldu256((const void*)(r0+c)),        x4=ldu256((const void*)(r0+4*N2+c));
      __m256i x1=ldu256((const void*)(r0+N2+c)),     x5=ldu256((const void*)(r0+5*N2+c));
      __m256i x2=ldu256((const void*)(r0+2*N2+c)),   x6=ldu256((const void*)(r0+6*N2+c));
      __m256i x3=ldu256((const void*)(r0+3*N2+c)),   x7=ldu256((const void*)(r0+7*N2+c));
      __m256i y0=vadd4(x0,x4,p4,p4m1), z0=vshoup(vdiff4(x0,x4,p4),w4[0],ws4[0],pv);
      __m256i y1=vadd4(x1,x5,p4,p4m1), z1=vshoup(vdiff4(x1,x5,p4),w4[1],ws4[1],pv);
      __m256i y2=vadd4(x2,x6,p4,p4m1), z2=vshoup(vdiff4(x2,x6,p4),w4[2],ws4[2],pv);
      __m256i y3=vadd4(x3,x7,p4,p4m1), z3=vshoup(vdiff4(x3,x7,p4),w4[3],ws4[3],pv);
      __m256i p0=vadd4(y0,y2,p4,p4m1), q0=vshoup(vdiff4(y0,y2,p4),w2[0],ws2[0],pv);
      __m256i p1=vadd4(y1,y3,p4,p4m1), q1=vshoup(vdiff4(y1,y3,p4),w2[1],ws2[1],pv);
      __m256i p2=vadd4(z0,z2,p4,p4m1), q2=vshoup(vdiff4(z0,z2,p4),w2[0],ws2[0],pv);
      __m256i p3=vadd4(z1,z3,p4,p4m1), q3=vshoup(vdiff4(z1,z3,p4),w2[1],ws2[1],pv);
      stu256((void*)(r0+c),     vadd4(p0,p1,p4,p4m1));
      stu256((void*)(r0+N2+c),  vredx(vdiff4(p0,p1,p4),p4,p4m1));
      stu256((void*)(r0+2*N2+c),vadd4(q0,q1,p4,p4m1));
      stu256((void*)(r0+3*N2+c),vredx(vdiff4(q0,q1,p4),p4,p4m1));
      stu256((void*)(r0+4*N2+c),vadd4(p2,p3,p4,p4m1));
      stu256((void*)(r0+5*N2+c),vredx(vdiff4(p2,p3,p4),p4,p4m1));
      stu256((void*)(r0+6*N2+c),vadd4(q2,q3,p4,p4m1));
      stu256((void*)(r0+7*N2+c),vredx(vdiff4(q2,q3,p4),p4,p4m1));
    }
  }
}
TGT static void col_tail3_dif_range(u32*a,const u32*W,const u32*WS,u32 s0,u32 tb){
  const __m256i p4=_mm256_set1_epi32((int)P4),p4m1=_mm256_set1_epi32((int)P4M1),pv=_mm256_set1_epi32((int)P);
  __m256i w4[4],ws4[4],w2[2],ws2[2];
  for(int k=0;k<4;k++){ w4[k]=_mm256_set1_epi32((int)W[N1-8+k]); ws4[k]=_mm256_set1_epi32((int)WS[N1-8+k]); }
  for(int k=0;k<2;k++){ w2[k]=_mm256_set1_epi32((int)W[N1-4+k]); ws2[k]=_mm256_set1_epi32((int)WS[N1-4+k]); }
  for(u32 s=s0;s<s0+tb;s+=8){
    u32*r0=a+(size_t)s*N2;
    for(u32 c=0;c<N2;c+=8){
      __m256i x0=ldu256((const void*)(r0+c)),        x4=ldu256((const void*)(r0+4*N2+c));
      __m256i x1=ldu256((const void*)(r0+N2+c)),     x5=ldu256((const void*)(r0+5*N2+c));
      __m256i x2=ldu256((const void*)(r0+2*N2+c)),   x6=ldu256((const void*)(r0+6*N2+c));
      __m256i x3=ldu256((const void*)(r0+3*N2+c)),   x7=ldu256((const void*)(r0+7*N2+c));
      __m256i y0=vadd4(x0,x4,p4,p4m1), z0=vshoup(vdiff4(x0,x4,p4),w4[0],ws4[0],pv);
      __m256i y1=vadd4(x1,x5,p4,p4m1), z1=vshoup(vdiff4(x1,x5,p4),w4[1],ws4[1],pv);
      __m256i y2=vadd4(x2,x6,p4,p4m1), z2=vshoup(vdiff4(x2,x6,p4),w4[2],ws4[2],pv);
      __m256i y3=vadd4(x3,x7,p4,p4m1), z3=vshoup(vdiff4(x3,x7,p4),w4[3],ws4[3],pv);
      __m256i p0=vadd4(y0,y2,p4,p4m1), q0=vshoup(vdiff4(y0,y2,p4),w2[0],ws2[0],pv);
      __m256i p1=vadd4(y1,y3,p4,p4m1), q1=vshoup(vdiff4(y1,y3,p4),w2[1],ws2[1],pv);
      __m256i p2=vadd4(z0,z2,p4,p4m1), q2=vshoup(vdiff4(z0,z2,p4),w2[0],ws2[0],pv);
      __m256i p3=vadd4(z1,z3,p4,p4m1), q3=vshoup(vdiff4(z1,z3,p4),w2[1],ws2[1],pv);
      stu256((void*)(r0+c),     vadd4(p0,p1,p4,p4m1));
      stu256((void*)(r0+N2+c),  vredx(vdiff4(p0,p1,p4),p4,p4m1));
      stu256((void*)(r0+2*N2+c),vadd4(q0,q1,p4,p4m1));
      stu256((void*)(r0+3*N2+c),vredx(vdiff4(q0,q1,p4),p4,p4m1));
      stu256((void*)(r0+4*N2+c),vadd4(p2,p3,p4,p4m1));
      stu256((void*)(r0+5*N2+c),vredx(vdiff4(p2,p3,p4),p4,p4m1));
      stu256((void*)(r0+6*N2+c),vadd4(q2,q3,p4,p4m1));
      stu256((void*)(r0+7*N2+c),vredx(vdiff4(q2,q3,p4),p4,p4m1));
    }
  }
}

TGT static inline void bfd(__m256i&u,__m256i&v,__m256i w,__m256i ws,__m256i p4,__m256i p4m1,__m256i pv){
  __m256i t=vshoup(v,w,ws,pv);
  __m256i s=vadd4(u,t,p4,p4m1);
  v=vredx(vdiff4(u,t,p4),p4,p4m1);
  u=s;
}
TGT static void col_tail3_dit(u32*a,const u32*W,const u32*WS){
  const __m256i p4=_mm256_set1_epi32((int)P4),p4m1=_mm256_set1_epi32((int)P4M1),pv=_mm256_set1_epi32((int)P);
  __m256i w4[4],ws4[4],w2[2],ws2[2];
  for(int k=0;k<4;k++){ w4[k]=_mm256_set1_epi32((int)W[N1-8+k]); ws4[k]=_mm256_set1_epi32((int)WS[N1-8+k]); }
  for(int k=0;k<2;k++){ w2[k]=_mm256_set1_epi32((int)W[N1-4+k]); ws2[k]=_mm256_set1_epi32((int)WS[N1-4+k]); }
  __m256i w1v=_mm256_set1_epi32((int)W[N1-2]),ws1v=_mm256_set1_epi32((int)WS[N1-2]);
  for(u32 s=0;s<N1;s+=8){
    u32*r0=a+(size_t)s*N2;
    for(u32 c=0;c<N2;c+=8){
      __m256i x0=ldu256((const void*)(r0+c)),        x4=ldu256((const void*)(r0+4*N2+c));
      __m256i x1=ldu256((const void*)(r0+N2+c)),     x5=ldu256((const void*)(r0+5*N2+c));
      __m256i x2=ldu256((const void*)(r0+2*N2+c)),   x6=ldu256((const void*)(r0+6*N2+c));
      __m256i x3=ldu256((const void*)(r0+3*N2+c)),   x7=ldu256((const void*)(r0+7*N2+c));
      bfd(x0,x1,w1v,ws1v,p4,p4m1,pv);
      bfd(x2,x3,w1v,ws1v,p4,p4m1,pv);
      bfd(x4,x5,w1v,ws1v,p4,p4m1,pv);
      bfd(x6,x7,w1v,ws1v,p4,p4m1,pv);
      bfd(x0,x2,w2[0],ws2[0],p4,p4m1,pv);
      bfd(x1,x3,w2[1],ws2[1],p4,p4m1,pv);
      bfd(x4,x6,w2[0],ws2[0],p4,p4m1,pv);
      bfd(x5,x7,w2[1],ws2[1],p4,p4m1,pv);
      bfd(x0,x4,w4[0],ws4[0],p4,p4m1,pv);
      bfd(x1,x5,w4[1],ws4[1],p4,p4m1,pv);
      bfd(x2,x6,w4[2],ws4[2],p4,p4m1,pv);
      bfd(x3,x7,w4[3],ws4[3],p4,p4m1,pv);
      stu256((void*)(r0+c),     x0); stu256((void*)(r0+4*N2+c),x4);
      stu256((void*)(r0+N2+c),  x1); stu256((void*)(r0+5*N2+c),x5);
      stu256((void*)(r0+2*N2+c),x2); stu256((void*)(r0+6*N2+c),x6);
      stu256((void*)(r0+3*N2+c),x3); stu256((void*)(r0+7*N2+c),x7);
    }
  }
}
TGT static void col_tail3_dit_range(u32*a,const u32*W,const u32*WS,u32 s0,u32 tb){
  const __m256i p4=_mm256_set1_epi32((int)P4),p4m1=_mm256_set1_epi32((int)P4M1),pv=_mm256_set1_epi32((int)P);
  __m256i w4[4],ws4[4],w2[2],ws2[2];
  for(int k=0;k<4;k++){ w4[k]=_mm256_set1_epi32((int)W[N1-8+k]); ws4[k]=_mm256_set1_epi32((int)WS[N1-8+k]); }
  for(int k=0;k<2;k++){ w2[k]=_mm256_set1_epi32((int)W[N1-4+k]); ws2[k]=_mm256_set1_epi32((int)WS[N1-4+k]); }
  __m256i w1v=_mm256_set1_epi32((int)W[N1-2]),ws1v=_mm256_set1_epi32((int)WS[N1-2]);
  for(u32 s=s0;s<s0+tb;s+=8){
    u32*r0=a+(size_t)s*N2;
    for(u32 c=0;c<N2;c+=8){
      __m256i x0=ldu256((const void*)(r0+c)),        x4=ldu256((const void*)(r0+4*N2+c));
      __m256i x1=ldu256((const void*)(r0+N2+c)),     x5=ldu256((const void*)(r0+5*N2+c));
      __m256i x2=ldu256((const void*)(r0+2*N2+c)),   x6=ldu256((const void*)(r0+6*N2+c));
      __m256i x3=ldu256((const void*)(r0+3*N2+c)),   x7=ldu256((const void*)(r0+7*N2+c));
      bfd(x0,x1,w1v,ws1v,p4,p4m1,pv);
      bfd(x2,x3,w1v,ws1v,p4,p4m1,pv);
      bfd(x4,x5,w1v,ws1v,p4,p4m1,pv);
      bfd(x6,x7,w1v,ws1v,p4,p4m1,pv);
      bfd(x0,x2,w2[0],ws2[0],p4,p4m1,pv);
      bfd(x1,x3,w2[1],ws2[1],p4,p4m1,pv);
      bfd(x4,x6,w2[0],ws2[0],p4,p4m1,pv);
      bfd(x5,x7,w2[1],ws2[1],p4,p4m1,pv);
      bfd(x0,x4,w4[0],ws4[0],p4,p4m1,pv);
      bfd(x1,x5,w4[1],ws4[1],p4,p4m1,pv);
      bfd(x2,x6,w4[2],ws4[2],p4,p4m1,pv);
      bfd(x3,x7,w4[3],ws4[3],p4,p4m1,pv);
      stu256((void*)(r0+c),     x0); stu256((void*)(r0+4*N2+c),x4);
      stu256((void*)(r0+N2+c),  x1); stu256((void*)(r0+5*N2+c),x5);
      stu256((void*)(r0+2*N2+c),x2); stu256((void*)(r0+6*N2+c),x6);
      stu256((void*)(r0+3*N2+c),x3); stu256((void*)(r0+7*N2+c),x7);
    }
  }
}

TGT static void col_tr(u32*a,u32 dir){
  const __m256i p4=_mm256_set1_epi32((int)P4),p4m1=_mm256_set1_epi32((int)P4M1),pv=_mm256_set1_epi32((int)P);
  const u32*W = dir? JW : CW; const u32*WS = dir? JWS : CWS;
  if(!dir){
    for(int ph=0;ph<2;ph++){
      const u32 TB = ph ? CT_TB : N1, h0 = ph ? (CT_TB>>1) : (N1>>1), h1 = ph ? 8u : CT_TB;
      for(u32 s0=0;s0<N1;s0+=TB){
    for(u32 h=h0;h>=h1;h>>=1){
      const u32*w=W+(N1-2*h),*ws=WS+(N1-2*h);
      for(u32 s=s0;s<s0+TB;s+=2*h){ u32*r0=a+(size_t)s*N2,*r1=r0+(size_t)h*N2;
        for(u32 j=0;j<h;j++,r0+=N2,r1+=N2){
          __m256i wv=_mm256_set1_epi32((int)w[j]),wsv=_mm256_set1_epi32((int)ws[j]);
          if(h==(N1>>1)){
            for(u32 c=0;c<N2;c+=32){
              __m256i x0=ldu256((const void*)(r0+c));
              __m256i x1=ldu256((const void*)(r0+c+8));
              __m256i x2=ldu256((const void*)(r0+c+16));
              __m256i x3=ldu256((const void*)(r0+c+24));
              stu256((void*)(r1+c),vshoupb(_mm256_add_epi32(x0,p4),wv,wsv,pv));
              stu256((void*)(r1+c+8),vshoupb(_mm256_add_epi32(x1,p4),wv,wsv,pv));
              stu256((void*)(r1+c+16),vshoupb(_mm256_add_epi32(x2,p4),wv,wsv,pv));
              stu256((void*)(r1+c+24),vshoupb(_mm256_add_epi32(x3,p4),wv,wsv,pv));
            }
            continue;
          }
          for(u32 c=0;c<N2;c+=32){
            __m256i x0=ldu256((const void*)(r0+c)),y0=ldu256((const void*)(r1+c));
            __m256i x1=ldu256((const void*)(r0+c+8)),y1=ldu256((const void*)(r1+c+8));
            __m256i x2=ldu256((const void*)(r0+c+16)),y2=ldu256((const void*)(r1+c+16));
            __m256i x3=ldu256((const void*)(r0+c+24)),y3=ldu256((const void*)(r1+c+24));
            stu256((void*)(r0+c),vadd4(x0,y0,p4,p4m1));
            stu256((void*)(r0+c+8),vadd4(x1,y1,p4,p4m1));
            stu256((void*)(r0+c+16),vadd4(x2,y2,p4,p4m1));
            stu256((void*)(r0+c+24),vadd4(x3,y3,p4,p4m1));
            stu256((void*)(r1+c),vshoupb(vdiff4(x0,y0,p4),wv,wsv,pv));
            stu256((void*)(r1+c+8),vshoupb(vdiff4(x1,y1,p4),wv,wsv,pv));
            stu256((void*)(r1+c+16),vshoupb(vdiff4(x2,y2,p4),wv,wsv,pv));
            stu256((void*)(r1+c+24),vshoupb(vdiff4(x3,y3,p4),wv,wsv,pv));
          }
        }}
    }
        if(ph) col_tail3_dif_range(a,W,WS,s0,CT_TB);
      }
    }
  } else {
    for(int ph=0;ph<2;ph++){
      const u32 TB = ph ? N1 : CT_TB, h0 = ph ? CT_TB : 8u, h1 = ph ? (N1>>1) : (CT_TB>>1);
      for(u32 s0=0;s0<N1;s0+=TB){
        if(!ph) col_tail3_dit_range(a,W,WS,s0,CT_TB);
    for(u32 h=h0;h<=h1;h<<=1){
      const u32*w=W+(N1-2*h),*ws=WS+(N1-2*h);
      for(u32 s=s0;s<s0+TB;s+=2*h){ u32*r0=a+(size_t)s*N2,*r1=r0+(size_t)h*N2;
        for(u32 j=0;j<h;j++,r0+=N2,r1+=N2){
          __m256i wv=_mm256_set1_epi32((int)w[j]),wsv=_mm256_set1_epi32((int)ws[j]);
          for(u32 c=0;c<N2;c+=32){
            __m256i x0=ldu256((const void*)(r0+c)),y0=ldu256((const void*)(r1+c));
            __m256i x1=ldu256((const void*)(r0+c+8)),y1=ldu256((const void*)(r1+c+8));
            __m256i x2=ldu256((const void*)(r0+c+16)),y2=ldu256((const void*)(r1+c+16));
            __m256i x3=ldu256((const void*)(r0+c+24)),y3=ldu256((const void*)(r1+c+24));
            __m256i t0=vshoup(y0,wv,wsv,pv),t1=vshoup(y1,wv,wsv,pv),t2=vshoup(y2,wv,wsv,pv),t3=vshoup(y3,wv,wsv,pv);
            __m256i s0=_mm256_add_epi32(x0,t0);s0=_mm256_min_epu32(s0,_mm256_sub_epi32(s0,p4));
            __m256i s1=_mm256_add_epi32(x1,t1);s1=_mm256_min_epu32(s1,_mm256_sub_epi32(s1,p4));
            __m256i s2=_mm256_add_epi32(x2,t2);s2=_mm256_min_epu32(s2,_mm256_sub_epi32(s2,p4));
            __m256i s3=_mm256_add_epi32(x3,t3);s3=_mm256_min_epu32(s3,_mm256_sub_epi32(s3,p4));
            __m256i d0=_mm256_add_epi32(_mm256_sub_epi32(x0,t0),p4);d0=_mm256_min_epu32(d0,_mm256_sub_epi32(d0,p4));
            __m256i d1=_mm256_add_epi32(_mm256_sub_epi32(x1,t1),p4);d1=_mm256_min_epu32(d1,_mm256_sub_epi32(d1,p4));
            __m256i d2=_mm256_add_epi32(_mm256_sub_epi32(x2,t2),p4);d2=_mm256_min_epu32(d2,_mm256_sub_epi32(d2,p4));
            __m256i d3=_mm256_add_epi32(_mm256_sub_epi32(x3,t3),p4);d3=_mm256_min_epu32(d3,_mm256_sub_epi32(d3,p4));
            stu256((void*)(r0+c),s0);stu256((void*)(r0+c+8),s1);
            stu256((void*)(r0+c+16),s2);stu256((void*)(r0+c+24),s3);
            stu256((void*)(r1+c),d0);stu256((void*)(r1+c+8),d1);
            stu256((void*)(r1+c+16),d2);stu256((void*)(r1+c+24),d3);
          }
        }}
    }
      }
    }
  }
}
#define CVSTR 40
struct CvTable { u32 v[(size_t)256*CVSTR]; };
constexpr u32 powmod_const(u32 a,u32 e){
  u32 r=1;
  while(e){ if(e&1) r=(u32)((u64)r*a%P); a=(u32)((u64)a*a%P); e>>=1; }
  return r;
}
constexpr CvTable make_cv_const(bool inverse){
  CvTable table{};
  const u32 RM=(u32)((1ull<<32)%P);
  u32 root=powmod_const(3,(P-1)/NN);
  if(inverse) root=powmod_const(root,P-2);
  const u32 ninv=powmod_const(NN,P-2);
  for(u32 i=0;i<N1;i++){
    u32 rev=0;
    for(u32 b=0;b<8;b++) if(i&(1u<<b)) rev|=1u<<(7-b);
    u32 row_root=powmod_const(root,rev);
    u32 value=inverse?(u32)((u64)ninv*RM%P):RM;
    for(u32 t=0;t<32;t++){
      table.v[(size_t)i*CVSTR+t]=value;
      value=(u32)((u64)value*row_root%P);
    }
    table.v[(size_t)i*CVSTR+32]=inverse?(u32)((u64)value*NN%P):value;
    u32 step=powmod_const(row_root,32);
    table.v[(size_t)i*CVSTR+33]=step;
    table.v[(size_t)i*CVSTR+34]=(u32)(((u64)step<<32)/P);
  }
  return table;
}
alignas(64) static constexpr CvTable g_cvF=make_cv_const(false);
alignas(64) static constexpr CvTable g_cvI=make_cv_const(true);
TGT static void row_scale(u32*row,const u32*cv){
  const __m256i pv=_mm256_set1_epi32((int)P);
  __m256i pinv=_mm256_set1_epi32((int)g_pinv);
  __m256i c0=ldu256((const void*)(cv+0));
  __m256i c1=ldu256((const void*)(cv+8));
  __m256i c2=ldu256((const void*)(cv+16));
  __m256i c3=ldu256((const void*)(cv+24));
  __m256i stp=_mm256_set1_epi32((int)cv[33]);
  __m256i stps=_mm256_set1_epi32((int)cv[34]);
  for(u32 j=0;j<N2;j+=32){
    __m256i x0=ldu256((const void*)(row+j));
    __m256i x1=ldu256((const void*)(row+j+8));
    __m256i x2=ldu256((const void*)(row+j+16));
    __m256i x3=ldu256((const void*)(row+j+24));
    stu256((void*)(row+j),vmont(x0,c0,pv,pinv));
    stu256((void*)(row+j+8),vmont(x1,c1,pv,pinv));
    stu256((void*)(row+j+16),vmont(x2,c2,pv,pinv));
    stu256((void*)(row+j+24),vmont(x3,c3,pv,pinv));
    c0=vshoup(c0,stp,stps,pv); c1=vshoup(c1,stp,stps,pv);
    c2=vshoup(c2,stp,stps,pv); c3=vshoup(c3,stp,stps,pv);
  }
}
TGT static void row_scale2(u32*ra,u32*rb,const u32*cv){
  const __m256i pv=CPV;
  __m256i pinv=_mm256_set1_epi32((int)g_pinv);
  __m256i c0=ldu256((const void*)(cv+0));
  __m256i c1=ldu256((const void*)(cv+8));
  __m256i c2=ldu256((const void*)(cv+16));
  __m256i c3=ldu256((const void*)(cv+24));
  __m256i stp=_mm256_set1_epi32((int)cv[33]);
  __m256i stps=_mm256_set1_epi32((int)cv[34]);
  for(u32 j=0;j<N2;j+=32){
    __m256i x0=ldu256((const void*)(ra+j)),x1=ldu256((const void*)(ra+j+8));
    __m256i x2=ldu256((const void*)(ra+j+16)),x3=ldu256((const void*)(ra+j+24));
    __m256i y0=ldu256((const void*)(rb+j)),y1=ldu256((const void*)(rb+j+8));
    __m256i y2=ldu256((const void*)(rb+j+16)),y3=ldu256((const void*)(rb+j+24));
    stu256((void*)(ra+j),vmont(x0,c0,pv,pinv)); stu256((void*)(ra+j+8),vmont(x1,c1,pv,pinv));
    stu256((void*)(ra+j+16),vmont(x2,c2,pv,pinv)); stu256((void*)(ra+j+24),vmont(x3,c3,pv,pinv));
    stu256((void*)(rb+j),vmont(y0,c0,pv,pinv)); stu256((void*)(rb+j+8),vmont(y1,c1,pv,pinv));
    stu256((void*)(rb+j+16),vmont(y2,c2,pv,pinv)); stu256((void*)(rb+j+24),vmont(y3,c3,pv,pinv));
    c0=vshoup(c0,stp,stps,pv); c1=vshoup(c1,stp,stps,pv);
    c2=vshoup(c2,stp,stps,pv); c3=vshoup(c3,stp,stps,pv);
  }
}
static u32 g_pw[N1], g_pwi[N1];   
TGT static void fwd_pre(u32*a,const u32*src,u32 srclen){
  u32 rows=(srclen+N2-1)/N2;
  if(a!=src) for(u32 i=0;i<rows;i++){
    u32 lim=((i+1)*(u64)N2<=srclen)?N2:(u32)(srclen-(u64)i*N2);
    memcpy(a+(size_t)i*N2,src+(size_t)i*N2,(size_t)lim*4);
  }
  for(u32 i=rows;i<(N1>>1);i++) memset(a+(size_t)i*N2,0,(size_t)N2*4);
  col_tr(a,0);
}
TGT static void inv(u32*dst,u32 dstlen,u32*a){
  for(u32 i=0;i<N1;i+=2){
    row_dif2(a+(size_t)i*N2,a+(size_t)(i+1)*N2,1);
    row_scale(a+(size_t)i*N2,g_cvI.v+(size_t)i*CVSTR);
    row_scale(a+(size_t)(i+1)*N2,g_cvI.v+(size_t)(i+1)*CVSTR);
  }
  col_tr(a,1);
  { const __m256i pv=_mm256_set1_epi32((int)P),p2v=_mm256_set1_epi32((int)P2);
    const __m256i pm1=_mm256_set1_epi32((int)PM1),p2m1=_mm256_set1_epi32((int)P2-1);
    u32 i=0;
    for(;i+8<=dstlen;i+=8){
      __m256i v=ldu256((const void*)(a+i));
      v=_mm256_min_epu32(v,_mm256_sub_epi32(v,p2v));
      v=_mm256_min_epu32(v,_mm256_sub_epi32(v,pv));
      stu256((void*)(dst+i),v);
    }
    for(;i<dstlen;i++){ u32 v=a[i]; if(v>=P2)v-=P2; if(v>=P)v-=P; dst[i]=v; }
  }
}
TGT static void pointwise(u32*a,u32*b){
  const __m256i pv=_mm256_set1_epi32((int)P);
  __m256i pinv=_mm256_set1_epi32((int)g_pinv);
  u32 i=0;
  for(;i+64<=NN;i+=64){
    __m256i x0=ldu256((const void*)(a+i+0)),y0=ldu256((const void*)(b+i+0));
    __m256i x1=ldu256((const void*)(a+i+8)),y1=ldu256((const void*)(b+i+8));
    __m256i x2=ldu256((const void*)(a+i+16)),y2=ldu256((const void*)(b+i+16));
    __m256i x3=ldu256((const void*)(a+i+24)),y3=ldu256((const void*)(b+i+24));
    __m256i x4=ldu256((const void*)(a+i+32)),y4=ldu256((const void*)(b+i+32));
    __m256i x5=ldu256((const void*)(a+i+40)),y5=ldu256((const void*)(b+i+40));
    __m256i x6=ldu256((const void*)(a+i+48)),y6=ldu256((const void*)(b+i+48));
    __m256i x7=ldu256((const void*)(a+i+56)),y7=ldu256((const void*)(b+i+56));
    stu256((void*)(a+i+0),vmont(x0,y0,pv,pinv));
    stu256((void*)(a+i+8),vmont(x1,y1,pv,pinv));
    stu256((void*)(a+i+16),vmont(x2,y2,pv,pinv));
    stu256((void*)(a+i+24),vmont(x3,y3,pv,pinv));
    stu256((void*)(a+i+32),vmont(x4,y4,pv,pinv));
    stu256((void*)(a+i+40),vmont(x5,y5,pv,pinv));
    stu256((void*)(a+i+48),vmont(x6,y6,pv,pinv));
    stu256((void*)(a+i+56),vmont(x7,y7,pv,pinv));
  }
  for(;i<NN;i+=8){ __m256i x=ldu256((const void*)(a+i)),y=ldu256((const void*)(b+i)); stu256((void*)(a+i),vmont(x,y,pv,pinv)); }
}
TGT static void pw_row(u32*a,u32*b){
  const __m256i pv=_mm256_set1_epi32((int)P);
  __m256i pinv=_mm256_set1_epi32((int)g_pinv);
  for(u32 i=0;i<N2;i+=8)
    stu256((void*)(a+i),vmont(ldu256((const void*)(a+i)),ldu256((const void*)(b+i)),pv,pinv));
}
static const char* g_ip; static const char* g_ie;
static inline u32 nxt(){ while(g_ip<g_ie && (*g_ip<'0'||*g_ip>'9')) g_ip++; u32 v=0; while(g_ip<g_ie&&*g_ip>='0'&&*g_ip<='9') v=v*10+(u32)(*g_ip++-'0'); return v; }
struct FmtTabs { u32 P2T[100]; u32 T4[10000]; u32 T3[1000]; u32 B2d[256]; };
constexpr FmtTabs make_fmt(){
  FmtTabs t{};
  for(u32 i=0;i<100;i++) t.P2T[i]=(u32)('0'+i/10)|((u32)('0'+i%10)<<8);
  for(u32 a=0;a<100;a++){ u32 hh=t.P2T[a], o=a*100u;
    for(u32 b=0;b<100;b++) t.T4[o+b]=hh|(t.P2T[b]<<16); }
  for(u32 c=0;c<10;c++){ u32 hi=(u32)('0'+c), o=c*100u;
    for(u32 r=0;r<100;r++) t.T3[o+r]=hi|(t.P2T[r]<<8); }
  for(u32 d=0;d<256;d++) t.B2d[d]=(u32)((u64)d*((1ull<<32)%P)%P);
  return t;
}
alignas(64) static constexpr FmtTabs FMT = make_fmt();
#define P2T (FMT.P2T)
#define T4  (FMT.T4)
#define T3  (FMT.T3)
#define B2d (FMT.B2d)
static void init_t4(){} static void init_t3(){} static void init_b2d(){}

#define B2D_RSH ((u32)((1ull<<32)%P))   
TGT static void parse_fast(const char*p,const char*e,u32 la,u32 lb){
  u32 k=0;                       
  const u32 TOT=la+lb;
  const __m256i lo0=_mm256_set1_epi8((char)('0'-1));
  const __m256i hi1=_mm256_set1_epi8((char)('9'+1));
  const __m256i shufE=_mm256_setr_epi8(0,2,4,6,8,10,12,14,-1,-1,-1,-1,-1,-1,-1,-1,
                                       0,2,4,6,8,10,12,14,-1,-1,-1,-1,-1,-1,-1,-1);
  const __m256i shufO=_mm256_setr_epi8(1,3,5,7,9,11,13,15,-1,-1,-1,-1,-1,-1,-1,-1,
                                       1,3,5,7,9,11,13,15,-1,-1,-1,-1,-1,-1,-1,-1);
  const __m128i dasc=_mm_set1_epi8((char)0x30);
  const __m256i rv=_mm256_set1_epi32((int)B2D_RSH);
  while(p+32<=e && k<TOT){
    u32 m;
    {
      __m256i v=ldu256((const void*)p);
      __m256i g=_mm256_cmpgt_epi8(v,lo0), l=_mm256_cmpgt_epi8(hi1,v);
      m=(u32)_mm256_movemask_epi8(_mm256_and_si256(g,l));
      if((m==0x55555555u||m==0xAAAAAAAAu) && k+16u<=TOT && (k+16u<=la || k>=la)){
        __m256i s=_mm256_shuffle_epi8(v,m==0x55555555u?shufE:shufO);
        __m256i q=_mm256_permute4x64_epi64(s,0xD8);
        __m128i x=_mm_sub_epi8(_mm256_castsi256_si128(q),dasc);
        __m256i w0=_mm256_cvtepu8_epi32(x);
        __m256i w1=_mm256_cvtepu8_epi32(_mm_srli_si128(x,8));
        if(k+16u<=la){ stu256((void*)(g_A+k),w0); stu256((void*)(g_A+k+8),w1); }
        else { u32 t=k-la;
               stu256((void*)(g_B+t),_mm256_mullo_epi32(w0,rv));
               stu256((void*)(g_B+t+8),_mm256_mullo_epi32(w1,rv)); }
        k+=16u; p+=32; continue;
      }
    }
    while(m){ int b=__builtin_ctz(m); m&=m-1;
      u32 d=(u32)((unsigned char)p[b]-'0');
      if(k<la) g_A[k]=d; else g_B[k-la]=B2d[d];
      k++;
    }
    p+=32;
  }
  for(;p<e && k<TOT;p++){
    u32 c=(u32)(*p-'0'); if(c>9u) continue;
    if(k<la) g_A[k]=c; else g_B[k-la]=B2d[c];
    k++;
  }
}
static size_t emit_all(char*o,const u32*a,u32 n){
  char*s=o;
  { 
    u32 v=a[0]; u32 hi=v/10000u, lo=v-hi*10000u;
    u64 d=((u64)T4[lo]<<32)|(u64)T4[hi];
    u64 x=d^0x3030303030303030ull;
    u32 lz=(u32)(__builtin_ctzll(x|0x8000000000000000ull)>>3);
    *(u64*)(s)=d>>(8*lz); s+=8-lz;
  }
  u32 i=1;
  for(;i<n;i++){
    u32 v=a[i];
    if(v>=1000000u){
      u32 hi=v/10000u, lo=v-hi*10000u;         
      *(u16*)(s)=' '; *(u32*)(s+1)=T3[hi]; *(u32*)(s+4)=(u32)T4[lo]; s+=8;
    } else if(v>=100000u) {
      u32 hi=v/10000u, lo=v-hi*10000u;
      *(u64*)s=((u64)T4[lo]<<24)|((u64)P2T[hi]<<8)|(u64)' '; s+=7;
    } else {
      u32 hi=v/10000u, lo=v-hi*10000u;
      u64 d=((u64)T4[lo]<<32)|(u64)T4[hi];
      u64 x=d^0x3030303030303030ull;
      u32 lz=(u32)(__builtin_ctzll(x|0x8000000000000000ull)>>3);
      *(u16*)(s)=' '; *(u64*)(s+1)=d>>(8*lz); s+=9-lz;
    }
  }
  *s++='\n';
  return (size_t)(s-o);
}

TGT static inline void T8(V&r0,V&r1,V&r2,V&r3,V&r4,V&r5,V&r6,V&r7){
  __m256i p0=_mm256_unpacklo_epi32(r0,r1),p1=_mm256_unpackhi_epi32(r0,r1);
  __m256i p2=_mm256_unpacklo_epi32(r2,r3),p3=_mm256_unpackhi_epi32(r2,r3);
  __m256i pa=_mm256_unpacklo_epi32(r4,r5),pb=_mm256_unpackhi_epi32(r4,r5);
  __m256i pc=_mm256_unpacklo_epi32(r6,r7),pd=_mm256_unpackhi_epi32(r6,r7);
  __m256i q0=_mm256_unpacklo_epi64(p0,p2),q1=_mm256_unpackhi_epi64(p0,p2);
  __m256i q2=_mm256_unpacklo_epi64(p1,p3),q3=_mm256_unpackhi_epi64(p1,p3);
  __m256i q4=_mm256_unpacklo_epi64(pa,pc),q5=_mm256_unpackhi_epi64(pa,pc);
  __m256i q6=_mm256_unpacklo_epi64(pb,pd),q7=_mm256_unpackhi_epi64(pb,pd);
  r0=_mm256_permute2x128_si256(q0,q4,0x20); r1=_mm256_permute2x128_si256(q1,q5,0x20);
  r2=_mm256_permute2x128_si256(q2,q6,0x20); r3=_mm256_permute2x128_si256(q3,q7,0x20);
  r4=_mm256_permute2x128_si256(q0,q4,0x31); r5=_mm256_permute2x128_si256(q1,q5,0x31);
  r6=_mm256_permute2x128_si256(q2,q6,0x31); r7=_mm256_permute2x128_si256(q3,q7,0x31);
}
TGT static void tail8_fwd(u32*base,const u32*W,const u32*WS){
  const __m256i p4=CP4,p4m1=CP4M1,pv=CPV;
  const u32*LT=W+(N2-8); const u32*LTS=WS+(N2-8);
  for(u32 c=0;c<N2;c+=8){
    V r0=ldu256((const void*)(base+c)),        r1=ldu256((const void*)(base+N2+c));
    V r2=ldu256((const void*)(base+2*N2+c)),   r3=ldu256((const void*)(base+3*N2+c));
    V r4=ldu256((const void*)(base+4*N2+c)),   r5=ldu256((const void*)(base+5*N2+c));
    V r6=ldu256((const void*)(base+6*N2+c)),   r7=ldu256((const void*)(base+7*N2+c));
    T8(r0,r1,r2,r3,r4,r5,r6,r7);
#define BF_DIF(a,b,wi) do{ V t_=vadd4(a,b,p4,p4m1); \
    b=vshoup(vdiff4(a,b,p4),_mm256_set1_epi32((int)LT[wi]),_mm256_set1_epi32((int)LTS[wi]),pv); a=t_; }while(0)
    BF_DIF(r0,r4,0); BF_DIF(r1,r5,1); BF_DIF(r2,r6,2); BF_DIF(r3,r7,3);
    BF_DIF(r0,r2,4); BF_DIF(r1,r3,5); BF_DIF(r4,r6,4); BF_DIF(r5,r7,5);
#undef BF_DIF
#define BF_DIF1(a,b) do{ V t_=vadd4(a,b,p4,p4m1); b=vredx(vdiff4(a,b,p4),p4,p4m1); a=t_; }while(0)
    BF_DIF1(r0,r1); BF_DIF1(r2,r3); BF_DIF1(r4,r5); BF_DIF1(r6,r7);
#undef BF_DIF1
    T8(r0,r1,r2,r3,r4,r5,r6,r7);
    stu256((void*)(base+c),r0);        stu256((void*)(base+N2+c),r1);
    stu256((void*)(base+2*N2+c),r2);   stu256((void*)(base+3*N2+c),r3);
    stu256((void*)(base+4*N2+c),r4);   stu256((void*)(base+5*N2+c),r5);
    stu256((void*)(base+6*N2+c),r6);   stu256((void*)(base+7*N2+c),r7);
  }
}
TGT static void tail8_inv(u32*base,const u32*W,const u32*WS){
  const __m256i p4=CP4,p4m1=CP4M1,pv=CPV;
  const u32*LT=W+(N2-8); const u32*LTS=WS+(N2-8);
  for(u32 c=0;c<N2;c+=8){
    V r0=ldu256((const void*)(base+c)),        r1=ldu256((const void*)(base+N2+c));
    V r2=ldu256((const void*)(base+2*N2+c)),   r3=ldu256((const void*)(base+3*N2+c));
    V r4=ldu256((const void*)(base+4*N2+c)),   r5=ldu256((const void*)(base+5*N2+c));
    V r6=ldu256((const void*)(base+6*N2+c)),   r7=ldu256((const void*)(base+7*N2+c));
    T8(r0,r1,r2,r3,r4,r5,r6,r7);
#define BF_DIT1(a,b) do{ V t_=vadd4(a,b,p4,p4m1); b=vredx(vdiff4(a,b,p4),p4,p4m1); a=t_; }while(0)
    BF_DIT1(r0,r1); BF_DIT1(r2,r3); BF_DIT1(r4,r5); BF_DIT1(r6,r7);
#undef BF_DIT1
#define BF_DITW(a,b,wv,wsv) do{ V t_=vshoup(b,wv,wsv,pv); \
    V s_=vadd4(a,t_,p4,p4m1); b=vdiff4(a,t_,p4); a=s_; }while(0)
    { const V one=_mm256_set1_epi32(1);
      BF_DITW(r0,r2,one,one); BF_DITW(r4,r6,one,one); }
    { const V wv=_mm256_set1_epi32((int)LT[5]), wsv=_mm256_set1_epi32((int)LTS[5]);
      BF_DITW(r1,r3,wv,wsv); BF_DITW(r5,r7,wv,wsv); }
#define BF_DITJ(a,b,wi) do{ V t_=vshoup(b,_mm256_set1_epi32((int)LT[wi]),_mm256_set1_epi32((int)LTS[wi]),pv); \
    V s_=vadd4(a,t_,p4,p4m1); b=vdiff4(a,t_,p4); a=s_; }while(0)
    BF_DITJ(r0,r4,0); BF_DITJ(r1,r5,1); BF_DITJ(r2,r6,2); BF_DITJ(r3,r7,3);
#undef BF_DITJ
#undef BF_DITW
    T8(r0,r1,r2,r3,r4,r5,r6,r7);
    stu256((void*)(base+c),r0);        stu256((void*)(base+N2+c),r1);
    stu256((void*)(base+2*N2+c),r2);   stu256((void*)(base+3*N2+c),r3);
    stu256((void*)(base+4*N2+c),r4);   stu256((void*)(base+5*N2+c),r5);
    stu256((void*)(base+6*N2+c),r6);   stu256((void*)(base+7*N2+c),r7);
  }
}
TGT static void row_wide2(u32*ra,u32*rb,u32 dir){
  const u32*W = dir? IW : RW; const u32*WS = dir? IWS : RWS;
  if(!dir){
    st2_fwd<256>(ra,rb,W+(N2-512),WS+(N2-512)); st2_fwd<128>(ra,rb,W+(N2-256),WS+(N2-256));
    st2_fwd<64>(ra,rb,W+(N2-128),WS+(N2-128));  st2_fwd<32>(ra,rb,W+(N2-64),WS+(N2-64));
    st2_fwd<16>(ra,rb,W+(N2-32),WS+(N2-32));    st2_fwd<8>(ra,rb,W+(N2-16),WS+(N2-16));
  } else {
    st2_inv<8>(ra,rb,W+(N2-16),WS+(N2-16));     st2_inv<16>(ra,rb,W+(N2-32),WS+(N2-32));
    st2_inv<32>(ra,rb,W+(N2-64),WS+(N2-64));    st2_inv<64>(ra,rb,W+(N2-128),WS+(N2-128));
    st2_inv<128>(ra,rb,W+(N2-256),WS+(N2-256)); st2_inv<256>(ra,rb,W+(N2-512),WS+(N2-512));
  }
}
TGT static void inv8(u32*dst,u32 dstlen,u32*a){
  for(u32 i=0;i<N1;i+=8){
    tail8_inv(a+(size_t)i*N2,IW,IWS);
    for(u32 k=0;k<8;k+=2) row_wide2(a+(size_t)(i+k)*N2,a+(size_t)(i+k+1)*N2,1);
    for(u32 k=0;k<8;k++) row_scale(a+(size_t)(i+k)*N2,g_cvI.v+(size_t)(i+k)*CVSTR);
  }
  col_tr(a,1);
  { const __m256i pv=_mm256_set1_epi32((int)P),p2v=_mm256_set1_epi32((int)P2);
    const __m256i pm1=_mm256_set1_epi32((int)PM1),p2m1=_mm256_set1_epi32((int)P2-1);
    (void)pm1;(void)p2m1;
    u32 i=0;
    for(;i+8<=dstlen;i+=8){
      __m256i v=ldu256((const void*)(a+i));
      v=_mm256_min_epu32(v,_mm256_sub_epi32(v,p2v));
      v=_mm256_min_epu32(v,_mm256_sub_epi32(v,pv));
      stu256((void*)(dst+i),v);
    }
    for(;i<dstlen;i++){ u32 v=a[i]; if(v>=P2)v-=P2; if(v>=P)v-=P; dst[i]=v; }
  }
}

TGT static void solve_all(u32 la,u32 lb){
  fwd_pre(g_A,g_A,la);
  fwd_pre(g_B,g_B,lb);
  for(u32 i=0;i<N1;i+=8){
    for(u32 k=0;k<8;k++)
      row_scale2(g_A+(size_t)(i+k)*N2, g_B+(size_t)(i+k)*N2, g_cvF.v+(size_t)(i+k)*CVSTR);
    for(u32 k=0;k<8;k+=2) row_wide2(g_A+(size_t)(i+k)*N2, g_A+(size_t)(i+k+1)*N2, 0);
    tail8_fwd(g_A+(size_t)i*N2, RW, RWS);
    for(u32 k=0;k<8;k+=2) row_wide2(g_B+(size_t)(i+k)*N2, g_B+(size_t)(i+k+1)*N2, 0);
    tail8_fwd(g_B+(size_t)i*N2, RW, RWS);
    for(u32 k=0;k<8;k++) pw_row(g_A+(size_t)(i+k)*N2, g_B+(size_t)(i+k)*N2);
  }
  u32 tot=la+lb-1;
  inv8(g_A,tot,g_A);
}

}
#undef B2D_RSH
#undef B2d
#undef BF_DIF
#undef BF_DIF1
#undef BF_DIT1
#undef BF_DITJ
#undef BF_DITW
#undef CP4
#undef CP4M1
#undef CPV
#undef CT_TB
#undef CVSTR
#undef CW
#undef CWS
#undef IW
#undef IWS
#undef JW
#undef JWS
#undef N1
#undef N2
#undef NN
#undef P
#undef P2
#undef P2T
#undef P4
#undef P4M1
#undef PM1
#undef REV1
#undef RW
#undef RWS
#undef T3
#undef T4
#undef TGT
#undef g_R2
#undef g_ninv
#undef g_pinv
#undef g_w
namespace Big {
typedef uint32_t u32; typedef uint64_t u64; typedef uint16_t u16;
#define TGT __attribute__((target("avx2")))

TGT static inline __m256i ldu256(const void *p){
  __m256i r; __asm__("vmovdqu %1, %0" : "=x"(r) : "m"(*(const __m256i *)p)); return r; }
TGT static inline void stu256(void *p, __m256i v){
  __asm__ volatile("vmovdqu %1, %0" : "=m"(*(__m256i *)p) : "x"(v)); }
#define P     13631489u
#define PM1   (P-1u)
#define P2    (2u*P)
#define P4    (4u*P)
#define P4M1  (4u*P-1u)
#define N1    512u
#define N2    512u
#define NN    (N1*N2)
#define CT_TB 128u   
TGT static inline __m256i vmulhi32(__m256i a, __m256i b){
  __m256i e=_mm256_mul_epu32(a,b);
  __m256i o=_mm256_mul_epu32(_mm256_srli_epi64(a,32),_mm256_srli_epi64(b,32));
  e=_mm256_srli_epi64(e,32);
  return _mm256_blend_epi32(e,o,0xAA);
}
TGT static inline __m128i vmulhi32_128(__m128i a, __m128i b){
  __m128i e=_mm_mul_epu32(a,b);
  __m128i o=_mm_mul_epu32(_mm_srli_epi64(a,32),_mm_srli_epi64(b,32));
  e=_mm_srli_epi64(e,32);
  return _mm_blend_epi32(e,o,0xAA);
}
TGT static inline __m256i vadd4(__m256i x,__m256i y,__m256i p4,__m256i p4m1){
  __m256i u=_mm256_add_epi32(x,y);
  return _mm256_min_epu32(u,_mm256_sub_epi32(u,p4));
}
TGT static inline __m256i vdiff4(__m256i x,__m256i y,__m256i p4){ return _mm256_add_epi32(_mm256_sub_epi32(x,y),p4); }

TGT static inline __m256i vmulhi32b(__m256i a,__m256i b){
  __m256i e=_mm256_mul_epu32(a,b);
  __m256i o=_mm256_mul_epu32(_mm256_srli_epi64(a,32),b);
  e=_mm256_srli_epi64(e,32);
  return _mm256_blend_epi32(e,o,0xAA);
}
TGT static inline __m256i vshoupb(__m256i a,__m256i w,__m256i ws,__m256i pv){
  __m256i t=_mm256_mullo_epi32(a,w);
  __m256i q=vmulhi32b(a,ws);
  return _mm256_sub_epi32(t,_mm256_mullo_epi32(q,pv));
}
TGT static inline __m256i vshoup(__m256i a,__m256i w,__m256i ws,__m256i pv){
  __m256i t=_mm256_mullo_epi32(a,w);
  __m256i q=vmulhi32(a,ws);
  return _mm256_sub_epi32(t,_mm256_mullo_epi32(q,pv));
}
TGT static inline __m256i vmont(__m256i a,__m256i b,__m256i pv,__m256i pinv){
  __m256i tlo=_mm256_mullo_epi32(a,b);
  __m256i thi=vmulhi32(a,b);
  __m256i m=_mm256_mullo_epi32(tlo,pinv);
  __m256i mphi=vmulhi32b(m,pv);   
  __m256i nz=_mm256_andnot_si256(_mm256_cmpeq_epi32(tlo,_mm256_setzero_si256()),_mm256_set1_epi32(1));
  return _mm256_add_epi32(_mm256_add_epi32(thi,mphi),nz);
}

struct DI {
  unsigned long abi;
  const char *s; unsigned long sn;
  char *o; unsigned long ol; unsigned long os;
  char *e; unsigned long el; unsigned long es;
  const char *IB; unsigned long IBl;
  char *OB; unsigned long OBl;
  unsigned long tsc;
} __attribute__((packed));
static DI *find_duck(int argc, char **argv){
  unsigned long *p = (unsigned long *)(argv + argc + 1);
  while (*p) p++; p++;
  for (int i = 0; i < 32 && p[0]; i++, p += 2)
    if (p[0] == 0x6b637564UL) { DI *d = (DI *)p[1]; return (d && d->abi == 40) ? d : 0; }
  return 0;
}
static u32 powmod32(u32 a,u32 e){u32 r=1;while(e){if(e&1)r=(u32)((u64)r*a%P);a=(u32)((u64)a*a%P);e>>=1;}return r;}
static inline u32 ws_of(u32 w){ return (u32)(((u64)w<<32)/P); }

struct SwTabs {
  u32 CW[64+N1],CWS[64+N1],JW[64+N1],JWS[64+N1];
  u32 RW[64+N2],RWS[64+N2],IW[64+N2],IWS[64+N2];
  u32 REV1[N1];
  u32 g_pinv,g_R2,g_w,g_ninv;
};
constexpr u32 cpow(u32 a,u32 e){ u32 r=1; while(e){ if(e&1) r=(u32)((u64)r*a%P); a=(u32)((u64)a*a%P); e>>=1; } return r; }
constexpr u32 cws(u32 w){ return (u32)(((u64)w<<32)/P); }
constexpr void ctab(u32*W,u32*WS,u32 L,u32 w){
  u32 h=L>>1;
  for(;;){
    u32 off=L-2*h, st=cpow(w,L/(2*h)), acc=1;
    for(u32 j=0;j<h;j++){ W[off+j]=acc; WS[off+j]=cws(acc); acc=(u32)((u64)acc*st%P); }
    if(h==1) break;
    h>>=1;
  }
}
constexpr SwTabs make_sw(){
  SwTabs t{};
  { u32 iv=1; for(int q=0;q<5;q++) iv*=2u-P*iv; t.g_pinv=0u-iv; }
  t.g_R2=(u32)(((u64)((1ull<<32)%P)*((1ull<<32)%P))%P);
  t.g_w=cpow(3,(P-1)/NN);
  t.g_ninv=cpow(NN,P-2);
  u32 wn1=cpow(t.g_w,N2), wn2=cpow(t.g_w,N1);
  ctab(t.CW,t.CWS,N1,wn1);
  ctab(t.JW,t.JWS,N1,cpow(wn1,P-2));
  ctab(t.RW,t.RWS,N2,wn2);
  ctab(t.IW,t.IWS,N2,cpow(wn2,P-2));
  { u32 l1=0; while((1u<<l1)<N1) l1++;
    for(u32 i=0;i<N1;i++){ u32 r=0; for(u32 b=0;b<l1;b++) if(i&(1u<<b)) r|=1u<<(l1-1-b); t.REV1[i]=r; } }
  return t;
}
alignas(64) static constexpr SwTabs SW = make_sw();
#define CW     (SW.CW)
#define CWS    (SW.CWS)
#define JW     (SW.JW)
#define JWS    (SW.JWS)
#define RW     (SW.RW)
#define RWS    (SW.RWS)
#define IW     (SW.IW)
#define IWS    (SW.IWS)
#define REV1   (SW.REV1)
#define g_pinv (SW.g_pinv)
#define g_R2   (SW.g_R2)
#define g_w    (SW.g_w)
#define g_ninv (SW.g_ninv)
static u32 g_A[NN], g_B[NN];

static void build_tab(u32 L,u32 w,u32*W,u32*WS){
  for(u32 h=L>>1;;h>>=1){
    u32 off=L-2*h;
    u32 st=powmod32(w,L/(2*h));
    for(u32 j=0,acc=1;j<h;j++){ W[off+j]=acc; WS[off+j]=ws_of(acc); acc=(u32)((u64)acc*st%P); }
    if(h==1) break;
  }
}
static void init_small(){}
TGT static void low3_dif(u32*p,const u32*LT,const u32*LTS){
  const __m256i p4=_mm256_set1_epi32((int)P4),p4m1=_mm256_set1_epi32((int)P4M1),pv=_mm256_set1_epi32((int)P);
  const __m128i p4s=_mm256_castsi256_si128(p4),p4m1s=_mm256_castsi256_si128(p4m1),pvs=_mm256_castsi256_si128(pv);
  __m256i x=ldu256((const void*)p);
  __m128i xl=_mm256_castsi256_si128(x),xh=_mm256_extracti128_si256(x,1);
  __m128i u=_mm_add_epi32(xl,xh); u=_mm_sub_epi32(u,_mm_and_si128(_mm_cmpgt_epi32(u,p4m1s),p4s));
  __m128i d=_mm_add_epi32(_mm_sub_epi32(xl,xh),p4s);
  __m128i t4=_mm_loadu_si128((const __m128i*)LT),ts4=_mm_loadu_si128((const __m128i*)LTS);
  __m128i dm=_mm_sub_epi32(_mm_mullo_epi32(d,t4),_mm_mullo_epi32(vmulhi32_128(d,ts4),pvs));
  __m128i yl=u,yh=dm;
  __m128i tw2=_mm_setr_epi32(0,0,1,(int)LT[5]);
  __m128i tws2=_mm_setr_epi32(0,0,(int)ws_of(1),(int)LTS[5]);
  #define DIF_H2(a) do{ __m128i t_=_mm_shuffle_epi32(a,_MM_SHUFFLE(1,0,3,2)); \
    __m128i u_=_mm_add_epi32(a,t_); __m128i u2=_mm_sub_epi32(u_,_mm_and_si128(_mm_cmpgt_epi32(u_,p4m1s),p4s)); \
    __m128i d_=_mm_add_epi32(_mm_sub_epi32(a,t_),p4s); \
    __m128i ds_=_mm_shuffle_epi32(d_,_MM_SHUFFLE(1,0,1,0)); \
    __m128i dd_=_mm_sub_epi32(_mm_mullo_epi32(ds_,tw2),_mm_mullo_epi32(vmulhi32_128(ds_,tws2),pvs)); \
    a=_mm_blend_epi32(u2,dd_,0xC); }while(0)
  #define DIF_H1(a) do{ __m128i t_=_mm_shuffle_epi32(a,_MM_SHUFFLE(2,3,0,1)); \
    __m128i u_=_mm_add_epi32(a,t_); __m128i u2=_mm_sub_epi32(u_,_mm_and_si128(_mm_cmpgt_epi32(u_,p4m1s),p4s)); \
    __m128i d_=_mm_add_epi32(_mm_sub_epi32(a,t_),p4s); \
    d_=_mm_sub_epi32(d_,_mm_and_si128(_mm_cmpgt_epi32(d_,p4m1s),p4s)); \
    __m128i ds_=_mm_shuffle_epi32(d_,_MM_SHUFFLE(2,3,0,1)); \
    a=_mm_blend_epi32(u2,ds_,0xA); }while(0)
  DIF_H2(yl); DIF_H2(yh);
  DIF_H1(yl); DIF_H1(yh);
  stu256((void*)p,_mm256_inserti128_si256(_mm256_castsi128_si256(yl),yh,1));
}
TGT static void low3_dit(u32*p,const u32*LT,const u32*LTS){
  const __m256i p4=_mm256_set1_epi32((int)P4),p4m1=_mm256_set1_epi32((int)P4M1),pv=_mm256_set1_epi32((int)P);
  const __m128i p4s=_mm256_castsi256_si128(p4),p4m1s=_mm256_castsi256_si128(p4m1),pvs=_mm256_castsi256_si128(pv);
  __m256i x=ldu256((const void*)p);
  __m128i yl=_mm256_castsi256_si128(x),yh=_mm256_extracti128_si256(x,1);
  #define DIT_H1(a) do{ __m128i t_=_mm_shuffle_epi32(a,_MM_SHUFFLE(2,3,0,1)); \
    __m128i s_=_mm_add_epi32(a,t_); __m128i s2=_mm_sub_epi32(s_,_mm_and_si128(_mm_cmpgt_epi32(s_,p4m1s),p4s)); \
    __m128i d_=_mm_add_epi32(_mm_sub_epi32(a,t_),p4s); \
    d_=_mm_sub_epi32(d_,_mm_and_si128(_mm_cmpgt_epi32(d_,p4m1s),p4s)); \
    __m128i ds_=_mm_shuffle_epi32(d_,_MM_SHUFFLE(2,3,0,1)); \
    a=_mm_blend_epi32(s2,ds_,0xA); }while(0)
  DIT_H1(yl); DIT_H1(yh);
  __m128i tw2=_mm_setr_epi32(1,(int)LT[5],0,0);
  __m128i tws2=_mm_setr_epi32(1,(int)LTS[5],0,0);
  #define DIT_H2(a) do{ __m128i t_=_mm_shuffle_epi32(a,_MM_SHUFFLE(1,0,3,2)); \
    __m128i v_=_mm_sub_epi32(_mm_mullo_epi32(t_,tw2),_mm_mullo_epi32(vmulhi32_128(t_,tws2),pvs)); \
    __m128i s_=_mm_add_epi32(a,v_); __m128i s2=_mm_sub_epi32(s_,_mm_and_si128(_mm_cmpgt_epi32(s_,p4m1s),p4s)); \
    __m128i d_=_mm_add_epi32(_mm_sub_epi32(a,v_),p4s); \
    __m128i dd_=_mm_shuffle_epi32(d_,_MM_SHUFFLE(1,0,1,0)); \
    a=_mm_blend_epi32(s2,dd_,0xC); }while(0)
  DIT_H2(yl); DIT_H2(yh);
  { __m128i t4=_mm_loadu_si128((const __m128i*)LT),ts4=_mm_loadu_si128((const __m128i*)LTS);
    __m128i t=_mm_sub_epi32(_mm_mullo_epi32(yh,t4),_mm_mullo_epi32(vmulhi32_128(yh,ts4),pvs));
    __m128i s=_mm_add_epi32(yl,t); s=_mm_sub_epi32(s,_mm_and_si128(_mm_cmpgt_epi32(s,p4m1s),p4s));
    __m128i d=_mm_add_epi32(_mm_sub_epi32(yl,t),p4s);
    yl=s; yh=d; }
  stu256((void*)p,_mm256_inserti128_si256(_mm256_castsi128_si256(yl),yh,1));
}

typedef __m256i V;
TGT static inline V vshx(V a,V w,V ws,V pv){V t=_mm256_mullo_epi32(a,w);V q=vmulhi32(a,ws);return _mm256_sub_epi32(t,_mm256_mullo_epi32(q,pv));}
TGT static inline V vredx(V a,V p4,V p4m1){return _mm256_min_epu32(a,_mm256_sub_epi32(a,p4));}
TGT static inline V vadd4x(V x,V y,V p4,V p4m1){V u=_mm256_add_epi32(x,y);return _mm256_min_epu32(u,_mm256_sub_epi32(u,p4));}
TGT static inline V vdiff4x(V x,V y,V p4){return _mm256_add_epi32(_mm256_sub_epi32(x,y),p4);}
TGT static inline void tail8_dif(u32*q,V w4,V ws4,V w2,V ws2,V p4,V p4m1,V pv){
  for(int v=0;v<8;v++){ V*pv_=(V*)(q+8*v); V x=pv_[0];
    V t=_mm256_permute2x128_si256(x,x,0x01);
    V s=vadd4x(x,t,p4,p4m1);
    V d=vshx(vdiff4x(t,x,p4),w4,ws4,pv);
    x=_mm256_blend_epi32(s,d,0xF0);
    t=_mm256_shuffle_epi32(x,0x4E);
    s=vadd4x(x,t,p4,p4m1);
    d=vshx(_mm256_shuffle_epi32(vdiff4x(x,t,p4),0x4E),w2,ws2,pv);
    x=_mm256_blend_epi32(s,d,0xCC);
    t=_mm256_shuffle_epi32(x,0xB1);
    s=vadd4x(x,t,p4,p4m1);
    d=vredx(_mm256_shuffle_epi32(vdiff4x(x,t,p4),0xB1),p4,p4m1);
    pv_[0]=_mm256_blend_epi32(s,d,0xAA);
  }
}
TGT static inline void tail8_dit(u32*q,V w4lo,V ws4lo,V w2d,V ws2d,V p4,V p4m1,V pv){
  for(int v=0;v<8;v++){ V*pv_=(V*)(q+8*v); V x=pv_[0];
    V t=_mm256_shuffle_epi32(x,0xB1);
    V s=vadd4x(x,t,p4,p4m1);
    V d=vredx(_mm256_shuffle_epi32(vdiff4x(x,t,p4),0xB1),p4,p4m1);
    x=_mm256_blend_epi32(s,d,0xAA);
    t=_mm256_shuffle_epi32(x,0x4E);
    V val=vshx(t,w2d,ws2d,pv);
    s=vadd4x(x,val,p4,p4m1);
    d=_mm256_shuffle_epi32(vdiff4x(x,val,p4),0x4E);
    x=_mm256_blend_epi32(s,d,0xCC);
    t=vshx(_mm256_permute2x128_si256(x,x,0x01),w4lo,ws4lo,pv);
    s=vadd4x(x,t,p4,p4m1);
    d=_mm256_permute2x128_si256(vdiff4x(x,t,p4),vdiff4x(x,t,p4),0x01);
    pv_[0]=_mm256_blend_epi32(s,d,0xF0);
  }
}
TGT static inline void tailconst(const u32*LT,const u32*LTS,V&w4,V&ws4,V&w4lo,V&ws4lo,V&w2,V&ws2,V&w2d,V&ws2d){
  __m128i l4=_mm_loadu_si128((const __m128i*)LT),ls4=_mm_loadu_si128((const __m128i*)LTS);
  w4=_mm256_inserti128_si256(_mm256_setzero_si256(),l4,1); ws4=_mm256_inserti128_si256(_mm256_setzero_si256(),ls4,1);
  w4lo=_mm256_castsi128_si256(l4); ws4lo=_mm256_castsi128_si256(ls4);
  w2=_mm256_setr_epi32(0,0,LT[4],LT[5],0,0,LT[4],LT[5]); ws2=_mm256_setr_epi32(0,0,LTS[4],LTS[5],0,0,LTS[4],LTS[5]);
  w2d=_mm256_setr_epi32(1,LT[5],0,0,1,LT[5],0,0); ws2d=_mm256_setr_epi32(1,LTS[5],0,0,1,LTS[5],0,0);
}

#define CP4   _mm256_set1_epi32((int)P4)
#define CP4M1 _mm256_set1_epi32((int)P4M1)
#define CPV   _mm256_set1_epi32((int)P)
template<u32 H> TGT static void st_fwd(u32*row,const u32*w,const u32*ws){
  const __m256i p4=CP4,p4m1=CP4M1,pv=CPV;
  for(u32 s=0;s<N2;s+=2*H){ u32*r0=row+s,*r1=r0+H;
    for(u32 j=0;j<H;j+=8){
      __m256i x=ldu256((const void*)(r0+j)),y=ldu256((const void*)(r1+j));
      stu256((void*)(r0+j),vadd4(x,y,p4,p4m1));
      stu256((void*)(r1+j),vshoup(vdiff4(x,y,p4),ldu256((const void*)(w+j)),ldu256((const void*)(ws+j)),pv));
    }}
}
template<u32 H> TGT static void st_inv(u32*row,const u32*w,const u32*ws){
  const __m256i p4=CP4,p4m1=CP4M1,pv=CPV;
  for(u32 s=0;s<N2;s+=2*H){ u32*r0=row+s,*r1=r0+H;
    for(u32 j=0;j<H;j+=8){
      __m256i x=ldu256((const void*)(r0+j)),y=ldu256((const void*)(r1+j));
      __m256i t=vshoup(y,ldu256((const void*)(w+j)),ldu256((const void*)(ws+j)),pv);
      __m256i sa=_mm256_add_epi32(x,t); sa=_mm256_min_epu32(sa,_mm256_sub_epi32(sa,p4));
      __m256i ds=_mm256_add_epi32(_mm256_sub_epi32(x,t),p4); ds=_mm256_min_epu32(ds,_mm256_sub_epi32(ds,p4));
      stu256((void*)(r0+j),sa); stu256((void*)(r1+j),ds);
    }}
}
template<u32 H> TGT static void st2_fwd(u32*ra,u32*rb,const u32*w,const u32*ws){
  const __m256i p4=CP4,p4m1=CP4M1,pv=CPV;
  for(u32 s=0;s<N2;s+=2*H){ u32*a0=ra+s,*a1=a0+H,*b0=rb+s,*b1=b0+H;
    for(u32 j=0;j<H;j+=8){
      __m256i x=ldu256((const void*)(a0+j)),y=ldu256((const void*)(a1+j));
      __m256i u=ldu256((const void*)(b0+j)),v=ldu256((const void*)(b1+j));
      __m256i wv=ldu256((const void*)(w+j)),wsv=ldu256((const void*)(ws+j));
      stu256((void*)(a0+j),vadd4(x,y,p4,p4m1));
      stu256((void*)(a1+j),vshoup(vdiff4(x,y,p4),wv,wsv,pv));
      stu256((void*)(b0+j),vadd4(u,v,p4,p4m1));
      stu256((void*)(b1+j),vshoup(vdiff4(u,v,p4),wv,wsv,pv));
    }}
}
template<u32 H> TGT static void st2_inv(u32*ra,u32*rb,const u32*w,const u32*ws){
  const __m256i p4=CP4,p4m1=CP4M1,pv=CPV;
  for(u32 s=0;s<N2;s+=2*H){ u32*a0=ra+s,*a1=a0+H,*b0=rb+s,*b1=b0+H;
    for(u32 j=0;j<H;j+=8){
      __m256i x=ldu256((const void*)(a0+j)),y=ldu256((const void*)(a1+j));
      __m256i u=ldu256((const void*)(b0+j)),v=ldu256((const void*)(b1+j));
      __m256i wv=ldu256((const void*)(w+j)),wsv=ldu256((const void*)(ws+j));
      __m256i t=vshoup(y,wv,wsv,pv),q=vshoup(v,wv,wsv,pv);
      __m256i sa=_mm256_add_epi32(x,t); sa=_mm256_min_epu32(sa,_mm256_sub_epi32(sa,p4));
      __m256i sb=_mm256_add_epi32(u,q); sb=_mm256_min_epu32(sb,_mm256_sub_epi32(sb,p4));
      __m256i da=_mm256_add_epi32(_mm256_sub_epi32(x,t),p4); da=_mm256_min_epu32(da,_mm256_sub_epi32(da,p4));
      __m256i db=_mm256_add_epi32(_mm256_sub_epi32(u,q),p4); db=_mm256_min_epu32(db,_mm256_sub_epi32(db,p4));
      stu256((void*)(a0+j),sa); stu256((void*)(a1+j),da);
      stu256((void*)(b0+j),sb); stu256((void*)(b1+j),db);
    }}
}
TGT static void tail_fwd_so(u32*row,V w4,V ws4,V w2,V ws2,V p4,V p4m1,V pv){
  for(u32 i=0;i<N2;i+=8){
    V x=ldu256((const void*)(row+i));
    V t=_mm256_permute2x128_si256(x,x,0x01);
    V s=vadd4x(x,t,p4,p4m1);
    V d=vshx(vdiff4x(t,x,p4),w4,ws4,pv);
    stu256((void*)(row+i),_mm256_blend_epi32(s,d,0xF0));
  }
  for(u32 i=0;i<N2;i+=8){
    V x=ldu256((const void*)(row+i));
    V t=_mm256_shuffle_epi32(x,0x4E);
    V s=vadd4x(x,t,p4,p4m1);
    V d=vshx(_mm256_shuffle_epi32(vdiff4x(x,t,p4),0x4E),w2,ws2,pv);
    stu256((void*)(row+i),_mm256_blend_epi32(s,d,0xCC));
  }
  for(u32 i=0;i<N2;i+=8){
    V x=ldu256((const void*)(row+i));
    V t=_mm256_shuffle_epi32(x,0xB1);
    V s=vadd4x(x,t,p4,p4m1);
    V d=vredx(_mm256_shuffle_epi32(vdiff4x(x,t,p4),0xB1),p4,p4m1);
    stu256((void*)(row+i),_mm256_blend_epi32(s,d,0xAA));
  }
}
TGT static void tail_inv_so(u32*row,V w4lo,V ws4lo,V w2d,V ws2d,V p4,V p4m1,V pv){
  for(u32 i=0;i<N2;i+=8){
    V x=ldu256((const void*)(row+i));
    V t=_mm256_shuffle_epi32(x,0xB1);
    V s=vadd4x(x,t,p4,p4m1);
    V d=vredx(_mm256_shuffle_epi32(vdiff4x(x,t,p4),0xB1),p4,p4m1);
    stu256((void*)(row+i),_mm256_blend_epi32(s,d,0xAA));
  }
  for(u32 i=0;i<N2;i+=8){
    V x=ldu256((const void*)(row+i));
    V t=_mm256_shuffle_epi32(x,0x4E);
    V val=vshx(t,w2d,ws2d,pv);
    V s=vadd4x(x,val,p4,p4m1);
    V d=_mm256_shuffle_epi32(vdiff4x(x,val,p4),0x4E);
    stu256((void*)(row+i),_mm256_blend_epi32(s,d,0xCC));
  }
  for(u32 i=0;i<N2;i+=8){
    V x=ldu256((const void*)(row+i));
    V t=vshx(_mm256_permute2x128_si256(x,x,0x01),w4lo,ws4lo,pv);
    V s=vadd4x(x,t,p4,p4m1);
    V d=_mm256_permute2x128_si256(vdiff4x(x,t,p4),vdiff4x(x,t,p4),0x01);
    stu256((void*)(row+i),_mm256_blend_epi32(s,d,0xF0));
  }
}
TGT static void row_dif(u32*row,u32 dir){
  const u32*W = dir? IW : RW; const u32*WS = dir? IWS : RWS;
  V w4,ws4,w4lo,ws4lo,w2,ws2,w2d,ws2d;
  tailconst(W+(N2-8),WS+(N2-8),w4,ws4,w4lo,ws4lo,w2,ws2,w2d,ws2d);
  if(!dir){
    st_fwd<256>(row,W+(N2-512),WS+(N2-512)); st_fwd<128>(row,W+(N2-256),WS+(N2-256));
    st_fwd<64>(row,W+(N2-128),WS+(N2-128));  st_fwd<32>(row,W+(N2-64),WS+(N2-64));
    st_fwd<16>(row,W+(N2-32),WS+(N2-32));    st_fwd<8>(row,W+(N2-16),WS+(N2-16));
    tail_fwd_so(row,w4,ws4,w2,ws2,CP4,CP4M1,CPV);
  } else {
    tail_inv_so(row,w4lo,ws4lo,w2d,ws2d,CP4,CP4M1,CPV);
    st_inv<8>(row,W+(N2-16),WS+(N2-16));     st_inv<16>(row,W+(N2-32),WS+(N2-32));
    st_inv<32>(row,W+(N2-64),WS+(N2-64));    st_inv<64>(row,W+(N2-128),WS+(N2-128));
    st_inv<128>(row,W+(N2-256),WS+(N2-256)); st_inv<256>(row,W+(N2-512),WS+(N2-512));
  }
}
TGT static void row_dif2(u32*ra,u32*rb,u32 dir){
  const u32*W = dir? IW : RW; const u32*WS = dir? IWS : RWS;
  V w4,ws4,w4lo,ws4lo,w2,ws2,w2d,ws2d;
  tailconst(W+(N2-8),WS+(N2-8),w4,ws4,w4lo,ws4lo,w2,ws2,w2d,ws2d);
  if(!dir){
    st2_fwd<256>(ra,rb,W+(N2-512),WS+(N2-512)); st2_fwd<128>(ra,rb,W+(N2-256),WS+(N2-256));
    st2_fwd<64>(ra,rb,W+(N2-128),WS+(N2-128));  st2_fwd<32>(ra,rb,W+(N2-64),WS+(N2-64));
    st2_fwd<16>(ra,rb,W+(N2-32),WS+(N2-32));    st2_fwd<8>(ra,rb,W+(N2-16),WS+(N2-16));
    tail_fwd_so(ra,w4,ws4,w2,ws2,CP4,CP4M1,CPV);
    tail_fwd_so(rb,w4,ws4,w2,ws2,CP4,CP4M1,CPV);
  } else {
    tail_inv_so(ra,w4lo,ws4lo,w2d,ws2d,CP4,CP4M1,CPV);
    tail_inv_so(rb,w4lo,ws4lo,w2d,ws2d,CP4,CP4M1,CPV);
    st2_inv<8>(ra,rb,W+(N2-16),WS+(N2-16));     st2_inv<16>(ra,rb,W+(N2-32),WS+(N2-32));
    st2_inv<32>(ra,rb,W+(N2-64),WS+(N2-64));    st2_inv<64>(ra,rb,W+(N2-128),WS+(N2-128));
    st2_inv<128>(ra,rb,W+(N2-256),WS+(N2-256)); st2_inv<256>(ra,rb,W+(N2-512),WS+(N2-512));
  }
}


TGT static void col_tail3_dif(u32*a,const u32*W,const u32*WS){
  const __m256i p4=_mm256_set1_epi32((int)P4),p4m1=_mm256_set1_epi32((int)P4M1),pv=_mm256_set1_epi32((int)P);
  __m256i w4[4],ws4[4],w2[2],ws2[2];
  for(int k=0;k<4;k++){ w4[k]=_mm256_set1_epi32((int)W[N1-8+k]); ws4[k]=_mm256_set1_epi32((int)WS[N1-8+k]); }
  for(int k=0;k<2;k++){ w2[k]=_mm256_set1_epi32((int)W[N1-4+k]); ws2[k]=_mm256_set1_epi32((int)WS[N1-4+k]); }
  for(u32 s=0;s<N1;s+=8){
    u32*r0=a+(size_t)s*N2;
    for(u32 c=0;c<N2;c+=8){
      __m256i x0=ldu256((const void*)(r0+c)),        x4=ldu256((const void*)(r0+4*N2+c));
      __m256i x1=ldu256((const void*)(r0+N2+c)),     x5=ldu256((const void*)(r0+5*N2+c));
      __m256i x2=ldu256((const void*)(r0+2*N2+c)),   x6=ldu256((const void*)(r0+6*N2+c));
      __m256i x3=ldu256((const void*)(r0+3*N2+c)),   x7=ldu256((const void*)(r0+7*N2+c));
      __m256i y0=vadd4(x0,x4,p4,p4m1), z0=vshoup(vdiff4(x0,x4,p4),w4[0],ws4[0],pv);
      __m256i y1=vadd4(x1,x5,p4,p4m1), z1=vshoup(vdiff4(x1,x5,p4),w4[1],ws4[1],pv);
      __m256i y2=vadd4(x2,x6,p4,p4m1), z2=vshoup(vdiff4(x2,x6,p4),w4[2],ws4[2],pv);
      __m256i y3=vadd4(x3,x7,p4,p4m1), z3=vshoup(vdiff4(x3,x7,p4),w4[3],ws4[3],pv);
      __m256i p0=vadd4(y0,y2,p4,p4m1), q0=vshoup(vdiff4(y0,y2,p4),w2[0],ws2[0],pv);
      __m256i p1=vadd4(y1,y3,p4,p4m1), q1=vshoup(vdiff4(y1,y3,p4),w2[1],ws2[1],pv);
      __m256i p2=vadd4(z0,z2,p4,p4m1), q2=vshoup(vdiff4(z0,z2,p4),w2[0],ws2[0],pv);
      __m256i p3=vadd4(z1,z3,p4,p4m1), q3=vshoup(vdiff4(z1,z3,p4),w2[1],ws2[1],pv);
      stu256((void*)(r0+c),     vadd4(p0,p1,p4,p4m1));
      stu256((void*)(r0+N2+c),  vredx(vdiff4(p0,p1,p4),p4,p4m1));
      stu256((void*)(r0+2*N2+c),vadd4(q0,q1,p4,p4m1));
      stu256((void*)(r0+3*N2+c),vredx(vdiff4(q0,q1,p4),p4,p4m1));
      stu256((void*)(r0+4*N2+c),vadd4(p2,p3,p4,p4m1));
      stu256((void*)(r0+5*N2+c),vredx(vdiff4(p2,p3,p4),p4,p4m1));
      stu256((void*)(r0+6*N2+c),vadd4(q2,q3,p4,p4m1));
      stu256((void*)(r0+7*N2+c),vredx(vdiff4(q2,q3,p4),p4,p4m1));
    }
  }
}
TGT static void col_tail3_dif_range(u32*a,const u32*W,const u32*WS,u32 s0,u32 tb){
  const __m256i p4=_mm256_set1_epi32((int)P4),p4m1=_mm256_set1_epi32((int)P4M1),pv=_mm256_set1_epi32((int)P);
  __m256i w4[4],ws4[4],w2[2],ws2[2];
  for(int k=0;k<4;k++){ w4[k]=_mm256_set1_epi32((int)W[N1-8+k]); ws4[k]=_mm256_set1_epi32((int)WS[N1-8+k]); }
  for(int k=0;k<2;k++){ w2[k]=_mm256_set1_epi32((int)W[N1-4+k]); ws2[k]=_mm256_set1_epi32((int)WS[N1-4+k]); }
  for(u32 s=s0;s<s0+tb;s+=8){
    u32*r0=a+(size_t)s*N2;
    for(u32 c=0;c<N2;c+=8){
      __m256i x0=ldu256((const void*)(r0+c)),        x4=ldu256((const void*)(r0+4*N2+c));
      __m256i x1=ldu256((const void*)(r0+N2+c)),     x5=ldu256((const void*)(r0+5*N2+c));
      __m256i x2=ldu256((const void*)(r0+2*N2+c)),   x6=ldu256((const void*)(r0+6*N2+c));
      __m256i x3=ldu256((const void*)(r0+3*N2+c)),   x7=ldu256((const void*)(r0+7*N2+c));
      __m256i y0=vadd4(x0,x4,p4,p4m1), z0=vshoup(vdiff4(x0,x4,p4),w4[0],ws4[0],pv);
      __m256i y1=vadd4(x1,x5,p4,p4m1), z1=vshoup(vdiff4(x1,x5,p4),w4[1],ws4[1],pv);
      __m256i y2=vadd4(x2,x6,p4,p4m1), z2=vshoup(vdiff4(x2,x6,p4),w4[2],ws4[2],pv);
      __m256i y3=vadd4(x3,x7,p4,p4m1), z3=vshoup(vdiff4(x3,x7,p4),w4[3],ws4[3],pv);
      __m256i p0=vadd4(y0,y2,p4,p4m1), q0=vshoup(vdiff4(y0,y2,p4),w2[0],ws2[0],pv);
      __m256i p1=vadd4(y1,y3,p4,p4m1), q1=vshoup(vdiff4(y1,y3,p4),w2[1],ws2[1],pv);
      __m256i p2=vadd4(z0,z2,p4,p4m1), q2=vshoup(vdiff4(z0,z2,p4),w2[0],ws2[0],pv);
      __m256i p3=vadd4(z1,z3,p4,p4m1), q3=vshoup(vdiff4(z1,z3,p4),w2[1],ws2[1],pv);
      stu256((void*)(r0+c),     vadd4(p0,p1,p4,p4m1));
      stu256((void*)(r0+N2+c),  vredx(vdiff4(p0,p1,p4),p4,p4m1));
      stu256((void*)(r0+2*N2+c),vadd4(q0,q1,p4,p4m1));
      stu256((void*)(r0+3*N2+c),vredx(vdiff4(q0,q1,p4),p4,p4m1));
      stu256((void*)(r0+4*N2+c),vadd4(p2,p3,p4,p4m1));
      stu256((void*)(r0+5*N2+c),vredx(vdiff4(p2,p3,p4),p4,p4m1));
      stu256((void*)(r0+6*N2+c),vadd4(q2,q3,p4,p4m1));
      stu256((void*)(r0+7*N2+c),vredx(vdiff4(q2,q3,p4),p4,p4m1));
    }
  }
}

TGT static inline void bfd(__m256i&u,__m256i&v,__m256i w,__m256i ws,__m256i p4,__m256i p4m1,__m256i pv){
  __m256i t=vshoup(v,w,ws,pv);
  __m256i s=vadd4(u,t,p4,p4m1);
  v=vredx(vdiff4(u,t,p4),p4,p4m1);
  u=s;
}
TGT static void col_tail3_dit(u32*a,const u32*W,const u32*WS){
  const __m256i p4=_mm256_set1_epi32((int)P4),p4m1=_mm256_set1_epi32((int)P4M1),pv=_mm256_set1_epi32((int)P);
  __m256i w4[4],ws4[4],w2[2],ws2[2];
  for(int k=0;k<4;k++){ w4[k]=_mm256_set1_epi32((int)W[N1-8+k]); ws4[k]=_mm256_set1_epi32((int)WS[N1-8+k]); }
  for(int k=0;k<2;k++){ w2[k]=_mm256_set1_epi32((int)W[N1-4+k]); ws2[k]=_mm256_set1_epi32((int)WS[N1-4+k]); }
  __m256i w1v=_mm256_set1_epi32((int)W[N1-2]),ws1v=_mm256_set1_epi32((int)WS[N1-2]);
  for(u32 s=0;s<N1;s+=8){
    u32*r0=a+(size_t)s*N2;
    for(u32 c=0;c<N2;c+=8){
      __m256i x0=ldu256((const void*)(r0+c)),        x4=ldu256((const void*)(r0+4*N2+c));
      __m256i x1=ldu256((const void*)(r0+N2+c)),     x5=ldu256((const void*)(r0+5*N2+c));
      __m256i x2=ldu256((const void*)(r0+2*N2+c)),   x6=ldu256((const void*)(r0+6*N2+c));
      __m256i x3=ldu256((const void*)(r0+3*N2+c)),   x7=ldu256((const void*)(r0+7*N2+c));
      bfd(x0,x1,w1v,ws1v,p4,p4m1,pv);
      bfd(x2,x3,w1v,ws1v,p4,p4m1,pv);
      bfd(x4,x5,w1v,ws1v,p4,p4m1,pv);
      bfd(x6,x7,w1v,ws1v,p4,p4m1,pv);
      bfd(x0,x2,w2[0],ws2[0],p4,p4m1,pv);
      bfd(x1,x3,w2[1],ws2[1],p4,p4m1,pv);
      bfd(x4,x6,w2[0],ws2[0],p4,p4m1,pv);
      bfd(x5,x7,w2[1],ws2[1],p4,p4m1,pv);
      bfd(x0,x4,w4[0],ws4[0],p4,p4m1,pv);
      bfd(x1,x5,w4[1],ws4[1],p4,p4m1,pv);
      bfd(x2,x6,w4[2],ws4[2],p4,p4m1,pv);
      bfd(x3,x7,w4[3],ws4[3],p4,p4m1,pv);
      stu256((void*)(r0+c),     x0); stu256((void*)(r0+4*N2+c),x4);
      stu256((void*)(r0+N2+c),  x1); stu256((void*)(r0+5*N2+c),x5);
      stu256((void*)(r0+2*N2+c),x2); stu256((void*)(r0+6*N2+c),x6);
      stu256((void*)(r0+3*N2+c),x3); stu256((void*)(r0+7*N2+c),x7);
    }
  }
}
TGT static void col_tail3_dit_range(u32*a,const u32*W,const u32*WS,u32 s0,u32 tb){
  const __m256i p4=_mm256_set1_epi32((int)P4),p4m1=_mm256_set1_epi32((int)P4M1),pv=_mm256_set1_epi32((int)P);
  __m256i w4[4],ws4[4],w2[2],ws2[2];
  for(int k=0;k<4;k++){ w4[k]=_mm256_set1_epi32((int)W[N1-8+k]); ws4[k]=_mm256_set1_epi32((int)WS[N1-8+k]); }
  for(int k=0;k<2;k++){ w2[k]=_mm256_set1_epi32((int)W[N1-4+k]); ws2[k]=_mm256_set1_epi32((int)WS[N1-4+k]); }
  __m256i w1v=_mm256_set1_epi32((int)W[N1-2]),ws1v=_mm256_set1_epi32((int)WS[N1-2]);
  for(u32 s=s0;s<s0+tb;s+=8){
    u32*r0=a+(size_t)s*N2;
    for(u32 c=0;c<N2;c+=8){
      __m256i x0=ldu256((const void*)(r0+c)),        x4=ldu256((const void*)(r0+4*N2+c));
      __m256i x1=ldu256((const void*)(r0+N2+c)),     x5=ldu256((const void*)(r0+5*N2+c));
      __m256i x2=ldu256((const void*)(r0+2*N2+c)),   x6=ldu256((const void*)(r0+6*N2+c));
      __m256i x3=ldu256((const void*)(r0+3*N2+c)),   x7=ldu256((const void*)(r0+7*N2+c));
      bfd(x0,x1,w1v,ws1v,p4,p4m1,pv);
      bfd(x2,x3,w1v,ws1v,p4,p4m1,pv);
      bfd(x4,x5,w1v,ws1v,p4,p4m1,pv);
      bfd(x6,x7,w1v,ws1v,p4,p4m1,pv);
      bfd(x0,x2,w2[0],ws2[0],p4,p4m1,pv);
      bfd(x1,x3,w2[1],ws2[1],p4,p4m1,pv);
      bfd(x4,x6,w2[0],ws2[0],p4,p4m1,pv);
      bfd(x5,x7,w2[1],ws2[1],p4,p4m1,pv);
      bfd(x0,x4,w4[0],ws4[0],p4,p4m1,pv);
      bfd(x1,x5,w4[1],ws4[1],p4,p4m1,pv);
      bfd(x2,x6,w4[2],ws4[2],p4,p4m1,pv);
      bfd(x3,x7,w4[3],ws4[3],p4,p4m1,pv);
      stu256((void*)(r0+c),     x0); stu256((void*)(r0+4*N2+c),x4);
      stu256((void*)(r0+N2+c),  x1); stu256((void*)(r0+5*N2+c),x5);
      stu256((void*)(r0+2*N2+c),x2); stu256((void*)(r0+6*N2+c),x6);
      stu256((void*)(r0+3*N2+c),x3); stu256((void*)(r0+7*N2+c),x7);
    }
  }
}

TGT static void col_tr(u32*a,u32 dir){
  const __m256i p4=_mm256_set1_epi32((int)P4),p4m1=_mm256_set1_epi32((int)P4M1),pv=_mm256_set1_epi32((int)P);
  const u32*W = dir? JW : CW; const u32*WS = dir? JWS : CWS;
  if(!dir){
    for(int ph=0;ph<2;ph++){
      const u32 TB = ph ? CT_TB : N1, h0 = ph ? (CT_TB>>1) : (N1>>1), h1 = ph ? 8u : CT_TB;
      for(u32 s0=0;s0<N1;s0+=TB){
    for(u32 h=h0;h>=h1;h>>=1){
      const u32*w=W+(N1-2*h),*ws=WS+(N1-2*h);
      for(u32 s=s0;s<s0+TB;s+=2*h){ u32*r0=a+(size_t)s*N2,*r1=r0+(size_t)h*N2;
        for(u32 j=0;j<h;j++,r0+=N2,r1+=N2){
          __m256i wv=_mm256_set1_epi32((int)w[j]),wsv=_mm256_set1_epi32((int)ws[j]);
          if(h==(N1>>1)){
            for(u32 c=0;c<N2;c+=32){
              __m256i x0=ldu256((const void*)(r0+c));
              __m256i x1=ldu256((const void*)(r0+c+8));
              __m256i x2=ldu256((const void*)(r0+c+16));
              __m256i x3=ldu256((const void*)(r0+c+24));
              stu256((void*)(r1+c),vshoupb(_mm256_add_epi32(x0,p4),wv,wsv,pv));
              stu256((void*)(r1+c+8),vshoupb(_mm256_add_epi32(x1,p4),wv,wsv,pv));
              stu256((void*)(r1+c+16),vshoupb(_mm256_add_epi32(x2,p4),wv,wsv,pv));
              stu256((void*)(r1+c+24),vshoupb(_mm256_add_epi32(x3,p4),wv,wsv,pv));
            }
            continue;
          }
          for(u32 c=0;c<N2;c+=32){
            __m256i x0=ldu256((const void*)(r0+c)),y0=ldu256((const void*)(r1+c));
            __m256i x1=ldu256((const void*)(r0+c+8)),y1=ldu256((const void*)(r1+c+8));
            __m256i x2=ldu256((const void*)(r0+c+16)),y2=ldu256((const void*)(r1+c+16));
            __m256i x3=ldu256((const void*)(r0+c+24)),y3=ldu256((const void*)(r1+c+24));
            stu256((void*)(r0+c),vadd4(x0,y0,p4,p4m1));
            stu256((void*)(r0+c+8),vadd4(x1,y1,p4,p4m1));
            stu256((void*)(r0+c+16),vadd4(x2,y2,p4,p4m1));
            stu256((void*)(r0+c+24),vadd4(x3,y3,p4,p4m1));
            stu256((void*)(r1+c),vshoupb(vdiff4(x0,y0,p4),wv,wsv,pv));
            stu256((void*)(r1+c+8),vshoupb(vdiff4(x1,y1,p4),wv,wsv,pv));
            stu256((void*)(r1+c+16),vshoupb(vdiff4(x2,y2,p4),wv,wsv,pv));
            stu256((void*)(r1+c+24),vshoupb(vdiff4(x3,y3,p4),wv,wsv,pv));
          }
        }}
    }
        if(ph) col_tail3_dif_range(a,W,WS,s0,CT_TB);
      }
    }
  } else {
    for(int ph=0;ph<2;ph++){
      const u32 TB = ph ? N1 : CT_TB, h0 = ph ? CT_TB : 8u, h1 = ph ? (N1>>1) : (CT_TB>>1);
      for(u32 s0=0;s0<N1;s0+=TB){
        if(!ph) col_tail3_dit_range(a,W,WS,s0,CT_TB);
    for(u32 h=h0;h<=h1;h<<=1){
      const u32*w=W+(N1-2*h),*ws=WS+(N1-2*h);
      for(u32 s=s0;s<s0+TB;s+=2*h){ u32*r0=a+(size_t)s*N2,*r1=r0+(size_t)h*N2;
        for(u32 j=0;j<h;j++,r0+=N2,r1+=N2){
          __m256i wv=_mm256_set1_epi32((int)w[j]),wsv=_mm256_set1_epi32((int)ws[j]);
          for(u32 c=0;c<N2;c+=32){
            __m256i x0=ldu256((const void*)(r0+c)),y0=ldu256((const void*)(r1+c));
            __m256i x1=ldu256((const void*)(r0+c+8)),y1=ldu256((const void*)(r1+c+8));
            __m256i x2=ldu256((const void*)(r0+c+16)),y2=ldu256((const void*)(r1+c+16));
            __m256i x3=ldu256((const void*)(r0+c+24)),y3=ldu256((const void*)(r1+c+24));
            __m256i t0=vshoup(y0,wv,wsv,pv),t1=vshoup(y1,wv,wsv,pv),t2=vshoup(y2,wv,wsv,pv),t3=vshoup(y3,wv,wsv,pv);
            __m256i s0=_mm256_add_epi32(x0,t0);s0=_mm256_min_epu32(s0,_mm256_sub_epi32(s0,p4));
            __m256i s1=_mm256_add_epi32(x1,t1);s1=_mm256_min_epu32(s1,_mm256_sub_epi32(s1,p4));
            __m256i s2=_mm256_add_epi32(x2,t2);s2=_mm256_min_epu32(s2,_mm256_sub_epi32(s2,p4));
            __m256i s3=_mm256_add_epi32(x3,t3);s3=_mm256_min_epu32(s3,_mm256_sub_epi32(s3,p4));
            __m256i d0=_mm256_add_epi32(_mm256_sub_epi32(x0,t0),p4);d0=_mm256_min_epu32(d0,_mm256_sub_epi32(d0,p4));
            __m256i d1=_mm256_add_epi32(_mm256_sub_epi32(x1,t1),p4);d1=_mm256_min_epu32(d1,_mm256_sub_epi32(d1,p4));
            __m256i d2=_mm256_add_epi32(_mm256_sub_epi32(x2,t2),p4);d2=_mm256_min_epu32(d2,_mm256_sub_epi32(d2,p4));
            __m256i d3=_mm256_add_epi32(_mm256_sub_epi32(x3,t3),p4);d3=_mm256_min_epu32(d3,_mm256_sub_epi32(d3,p4));
            stu256((void*)(r0+c),s0);stu256((void*)(r0+c+8),s1);
            stu256((void*)(r0+c+16),s2);stu256((void*)(r0+c+24),s3);
            stu256((void*)(r1+c),d0);stu256((void*)(r1+c+8),d1);
            stu256((void*)(r1+c+16),d2);stu256((void*)(r1+c+24),d3);
          }
        }}
    }
      }
    }
  }
}
#define CVSTR 40
struct CvTable { u32 v[(size_t)512*CVSTR]; };
constexpr u32 powmod_const(u32 a,u32 e){
  u32 r=1;
  while(e){ if(e&1) r=(u32)((u64)r*a%P); a=(u32)((u64)a*a%P); e>>=1; }
  return r;
}
constexpr CvTable make_cv_const(bool inverse){
  CvTable table{};
  const u32 RM=(u32)((1ull<<32)%P);
  u32 root=powmod_const(3,(P-1)/NN);
  if(inverse) root=powmod_const(root,P-2);
  const u32 ninv=powmod_const(NN,P-2);
  for(u32 i=0;i<N1;i++){
    u32 rev=0;
    for(u32 b=0;b<9;b++) if(i&(1u<<b)) rev|=1u<<(8-b);
    u32 row_root=powmod_const(root,rev);
    u32 value=inverse?(u32)((u64)ninv*RM%P):RM;
    for(u32 t=0;t<32;t++){
      table.v[(size_t)i*CVSTR+t]=value;
      value=(u32)((u64)value*row_root%P);
    }
    table.v[(size_t)i*CVSTR+32]=inverse?(u32)((u64)value*NN%P):value;
    u32 step=powmod_const(row_root,32);
    table.v[(size_t)i*CVSTR+33]=step;
    table.v[(size_t)i*CVSTR+34]=(u32)(((u64)step<<32)/P);
  }
  return table;
}
alignas(64) static constexpr CvTable g_cvF=make_cv_const(false);
alignas(64) static constexpr CvTable g_cvI=make_cv_const(true);
TGT static void row_scale(u32*row,const u32*cv){
  const __m256i pv=_mm256_set1_epi32((int)P);
  __m256i pinv=_mm256_set1_epi32((int)g_pinv);
  __m256i c0=ldu256((const void*)(cv+0));
  __m256i c1=ldu256((const void*)(cv+8));
  __m256i c2=ldu256((const void*)(cv+16));
  __m256i c3=ldu256((const void*)(cv+24));
  __m256i stp=_mm256_set1_epi32((int)cv[33]);
  __m256i stps=_mm256_set1_epi32((int)cv[34]);
  for(u32 j=0;j<N2;j+=32){
    __m256i x0=ldu256((const void*)(row+j));
    __m256i x1=ldu256((const void*)(row+j+8));
    __m256i x2=ldu256((const void*)(row+j+16));
    __m256i x3=ldu256((const void*)(row+j+24));
    stu256((void*)(row+j),vmont(x0,c0,pv,pinv));
    stu256((void*)(row+j+8),vmont(x1,c1,pv,pinv));
    stu256((void*)(row+j+16),vmont(x2,c2,pv,pinv));
    stu256((void*)(row+j+24),vmont(x3,c3,pv,pinv));
    c0=vshoup(c0,stp,stps,pv); c1=vshoup(c1,stp,stps,pv);
    c2=vshoup(c2,stp,stps,pv); c3=vshoup(c3,stp,stps,pv);
  }
}
TGT static void row_scale2(u32*ra,u32*rb,const u32*cv){
  const __m256i pv=CPV;
  __m256i pinv=_mm256_set1_epi32((int)g_pinv);
  __m256i c0=ldu256((const void*)(cv+0));
  __m256i c1=ldu256((const void*)(cv+8));
  __m256i c2=ldu256((const void*)(cv+16));
  __m256i c3=ldu256((const void*)(cv+24));
  __m256i stp=_mm256_set1_epi32((int)cv[33]);
  __m256i stps=_mm256_set1_epi32((int)cv[34]);
  for(u32 j=0;j<N2;j+=32){
    __m256i x0=ldu256((const void*)(ra+j)),x1=ldu256((const void*)(ra+j+8));
    __m256i x2=ldu256((const void*)(ra+j+16)),x3=ldu256((const void*)(ra+j+24));
    __m256i y0=ldu256((const void*)(rb+j)),y1=ldu256((const void*)(rb+j+8));
    __m256i y2=ldu256((const void*)(rb+j+16)),y3=ldu256((const void*)(rb+j+24));
    stu256((void*)(ra+j),vmont(x0,c0,pv,pinv)); stu256((void*)(ra+j+8),vmont(x1,c1,pv,pinv));
    stu256((void*)(ra+j+16),vmont(x2,c2,pv,pinv)); stu256((void*)(ra+j+24),vmont(x3,c3,pv,pinv));
    stu256((void*)(rb+j),vmont(y0,c0,pv,pinv)); stu256((void*)(rb+j+8),vmont(y1,c1,pv,pinv));
    stu256((void*)(rb+j+16),vmont(y2,c2,pv,pinv)); stu256((void*)(rb+j+24),vmont(y3,c3,pv,pinv));
    c0=vshoup(c0,stp,stps,pv); c1=vshoup(c1,stp,stps,pv);
    c2=vshoup(c2,stp,stps,pv); c3=vshoup(c3,stp,stps,pv);
  }
}
static u32 g_pw[N1], g_pwi[N1];   
TGT static void fwd_pre(u32*a,const u32*src,u32 srclen){
  u32 rows=(srclen+N2-1)/N2;
  if(a!=src) for(u32 i=0;i<rows;i++){
    u32 lim=((i+1)*(u64)N2<=srclen)?N2:(u32)(srclen-(u64)i*N2);
    memcpy(a+(size_t)i*N2,src+(size_t)i*N2,(size_t)lim*4);
  }
  for(u32 i=rows;i<(N1>>1);i++) memset(a+(size_t)i*N2,0,(size_t)N2*4);
  col_tr(a,0);
}
TGT static void inv(u32*dst,u32 dstlen,u32*a){
  for(u32 i=0;i<N1;i+=2){
    row_dif2(a+(size_t)i*N2,a+(size_t)(i+1)*N2,1);
    row_scale(a+(size_t)i*N2,g_cvI.v+(size_t)i*CVSTR);
    row_scale(a+(size_t)(i+1)*N2,g_cvI.v+(size_t)(i+1)*CVSTR);
  }
  col_tr(a,1);
  { const __m256i pv=_mm256_set1_epi32((int)P),p2v=_mm256_set1_epi32((int)P2);
    const __m256i pm1=_mm256_set1_epi32((int)PM1),p2m1=_mm256_set1_epi32((int)P2-1);
    u32 i=0;
    for(;i+8<=dstlen;i+=8){
      __m256i v=ldu256((const void*)(a+i));
      v=_mm256_min_epu32(v,_mm256_sub_epi32(v,p2v));
      v=_mm256_min_epu32(v,_mm256_sub_epi32(v,pv));
      stu256((void*)(dst+i),v);
    }
    for(;i<dstlen;i++){ u32 v=a[i]; if(v>=P2)v-=P2; if(v>=P)v-=P; dst[i]=v; }
  }
}
TGT static void pointwise(u32*a,u32*b){
  const __m256i pv=_mm256_set1_epi32((int)P);
  __m256i pinv=_mm256_set1_epi32((int)g_pinv);
  u32 i=0;
  for(;i+64<=NN;i+=64){
    __m256i x0=ldu256((const void*)(a+i+0)),y0=ldu256((const void*)(b+i+0));
    __m256i x1=ldu256((const void*)(a+i+8)),y1=ldu256((const void*)(b+i+8));
    __m256i x2=ldu256((const void*)(a+i+16)),y2=ldu256((const void*)(b+i+16));
    __m256i x3=ldu256((const void*)(a+i+24)),y3=ldu256((const void*)(b+i+24));
    __m256i x4=ldu256((const void*)(a+i+32)),y4=ldu256((const void*)(b+i+32));
    __m256i x5=ldu256((const void*)(a+i+40)),y5=ldu256((const void*)(b+i+40));
    __m256i x6=ldu256((const void*)(a+i+48)),y6=ldu256((const void*)(b+i+48));
    __m256i x7=ldu256((const void*)(a+i+56)),y7=ldu256((const void*)(b+i+56));
    stu256((void*)(a+i+0),vmont(x0,y0,pv,pinv));
    stu256((void*)(a+i+8),vmont(x1,y1,pv,pinv));
    stu256((void*)(a+i+16),vmont(x2,y2,pv,pinv));
    stu256((void*)(a+i+24),vmont(x3,y3,pv,pinv));
    stu256((void*)(a+i+32),vmont(x4,y4,pv,pinv));
    stu256((void*)(a+i+40),vmont(x5,y5,pv,pinv));
    stu256((void*)(a+i+48),vmont(x6,y6,pv,pinv));
    stu256((void*)(a+i+56),vmont(x7,y7,pv,pinv));
  }
  for(;i<NN;i+=8){ __m256i x=ldu256((const void*)(a+i)),y=ldu256((const void*)(b+i)); stu256((void*)(a+i),vmont(x,y,pv,pinv)); }
}
TGT static void pw_row(u32*a,u32*b){
  const __m256i pv=_mm256_set1_epi32((int)P);
  __m256i pinv=_mm256_set1_epi32((int)g_pinv);
  for(u32 i=0;i<N2;i+=8)
    stu256((void*)(a+i),vmont(ldu256((const void*)(a+i)),ldu256((const void*)(b+i)),pv,pinv));
}
static const char* g_ip; static const char* g_ie;
static inline u32 nxt(){ while(g_ip<g_ie && (*g_ip<'0'||*g_ip>'9')) g_ip++; u32 v=0; while(g_ip<g_ie&&*g_ip>='0'&&*g_ip<='9') v=v*10+(u32)(*g_ip++-'0'); return v; }
struct FmtTabs { u32 P2T[100]; u32 T4[10000]; u32 T3[1000]; u32 B2d[256]; };
constexpr FmtTabs make_fmt(){
  FmtTabs t{};
  for(u32 i=0;i<100;i++) t.P2T[i]=(u32)('0'+i/10)|((u32)('0'+i%10)<<8);
  for(u32 a=0;a<100;a++){ u32 hh=t.P2T[a], o=a*100u;
    for(u32 b=0;b<100;b++) t.T4[o+b]=hh|(t.P2T[b]<<16); }
  for(u32 c=0;c<10;c++){ u32 hi=(u32)('0'+c), o=c*100u;
    for(u32 r=0;r<100;r++) t.T3[o+r]=hi|(t.P2T[r]<<8); }
  for(u32 d=0;d<256;d++) t.B2d[d]=(u32)((u64)d*((1ull<<32)%P)%P);
  return t;
}
alignas(64) static constexpr FmtTabs FMT = make_fmt();
#define P2T (FMT.P2T)
#define T4  (FMT.T4)
#define T3  (FMT.T3)
#define B2d (FMT.B2d)
static void init_t4(){} static void init_t3(){} static void init_b2d(){}

#define B2D_RSH ((u32)((1ull<<32)%P))   
TGT static void parse_fast(const char*p,const char*e,u32 la,u32 lb){
  u32 k=0;                       
  const u32 TOT=la+lb;
  const __m256i lo0=_mm256_set1_epi8((char)('0'-1));
  const __m256i hi1=_mm256_set1_epi8((char)('9'+1));
  const __m256i shufE=_mm256_setr_epi8(0,2,4,6,8,10,12,14,-1,-1,-1,-1,-1,-1,-1,-1,
                                       0,2,4,6,8,10,12,14,-1,-1,-1,-1,-1,-1,-1,-1);
  const __m256i shufO=_mm256_setr_epi8(1,3,5,7,9,11,13,15,-1,-1,-1,-1,-1,-1,-1,-1,
                                       1,3,5,7,9,11,13,15,-1,-1,-1,-1,-1,-1,-1,-1);
  const __m128i dasc=_mm_set1_epi8((char)0x30);
  const __m256i rv=_mm256_set1_epi32((int)B2D_RSH);
  while(p+32<=e && k<TOT){
    u32 m;
    {
      __m256i v=ldu256((const void*)p);
      __m256i g=_mm256_cmpgt_epi8(v,lo0), l=_mm256_cmpgt_epi8(hi1,v);
      m=(u32)_mm256_movemask_epi8(_mm256_and_si256(g,l));
      if((m==0x55555555u||m==0xAAAAAAAAu) && k+16u<=TOT && (k+16u<=la || k>=la)){
        __m256i s=_mm256_shuffle_epi8(v,m==0x55555555u?shufE:shufO);
        __m256i q=_mm256_permute4x64_epi64(s,0xD8);
        __m128i x=_mm_sub_epi8(_mm256_castsi256_si128(q),dasc);
        __m256i w0=_mm256_cvtepu8_epi32(x);
        __m256i w1=_mm256_cvtepu8_epi32(_mm_srli_si128(x,8));
        if(k+16u<=la){ stu256((void*)(g_A+k),w0); stu256((void*)(g_A+k+8),w1); }
        else { u32 t=k-la;
               stu256((void*)(g_B+t),_mm256_mullo_epi32(w0,rv));
               stu256((void*)(g_B+t+8),_mm256_mullo_epi32(w1,rv)); }
        k+=16u; p+=32; continue;
      }
    }
    while(m){ int b=__builtin_ctz(m); m&=m-1;
      u32 d=(u32)((unsigned char)p[b]-'0');
      if(k<la) g_A[k]=d; else g_B[k-la]=B2d[d];
      k++;
    }
    p+=32;
  }
  for(;p<e && k<TOT;p++){
    u32 c=(u32)(*p-'0'); if(c>9u) continue;
    if(k<la) g_A[k]=c; else g_B[k-la]=B2d[c];
    k++;
  }
}
static size_t emit_all(char*o,const u32*a,u32 n){
  char*s=o;
  { 
    u32 v=a[0]; u32 hi=v/10000u, lo=v-hi*10000u;
    u64 d=((u64)T4[lo]<<32)|(u64)T4[hi];
    u64 x=d^0x3030303030303030ull;
    u32 lz=(u32)(__builtin_ctzll(x|0x8000000000000000ull)>>3);
    *(u64*)(s)=d>>(8*lz); s+=8-lz;
  }
  u32 i=1;
  for(;i<n;i++){
    u32 v=a[i];
    if(v>=1000000u){
      u32 hi=v/10000u, lo=v-hi*10000u;         
      *(u16*)(s)=' '; *(u32*)(s+1)=T3[hi]; *(u32*)(s+4)=(u32)T4[lo]; s+=8;
    } else if(v>=100000u) {
      u32 hi=v/10000u, lo=v-hi*10000u;
      *(u64*)s=((u64)T4[lo]<<24)|((u64)P2T[hi]<<8)|(u64)' '; s+=7;
    } else {
      u32 hi=v/10000u, lo=v-hi*10000u;
      u64 d=((u64)T4[lo]<<32)|(u64)T4[hi];
      u64 x=d^0x3030303030303030ull;
      u32 lz=(u32)(__builtin_ctzll(x|0x8000000000000000ull)>>3);
      *(u16*)(s)=' '; *(u64*)(s+1)=d>>(8*lz); s+=9-lz;
    }
  }
  *s++='\n';
  return (size_t)(s-o);
}

TGT static inline void T8(V&r0,V&r1,V&r2,V&r3,V&r4,V&r5,V&r6,V&r7){
  __m256i p0=_mm256_unpacklo_epi32(r0,r1),p1=_mm256_unpackhi_epi32(r0,r1);
  __m256i p2=_mm256_unpacklo_epi32(r2,r3),p3=_mm256_unpackhi_epi32(r2,r3);
  __m256i pa=_mm256_unpacklo_epi32(r4,r5),pb=_mm256_unpackhi_epi32(r4,r5);
  __m256i pc=_mm256_unpacklo_epi32(r6,r7),pd=_mm256_unpackhi_epi32(r6,r7);
  __m256i q0=_mm256_unpacklo_epi64(p0,p2),q1=_mm256_unpackhi_epi64(p0,p2);
  __m256i q2=_mm256_unpacklo_epi64(p1,p3),q3=_mm256_unpackhi_epi64(p1,p3);
  __m256i q4=_mm256_unpacklo_epi64(pa,pc),q5=_mm256_unpackhi_epi64(pa,pc);
  __m256i q6=_mm256_unpacklo_epi64(pb,pd),q7=_mm256_unpackhi_epi64(pb,pd);
  r0=_mm256_permute2x128_si256(q0,q4,0x20); r1=_mm256_permute2x128_si256(q1,q5,0x20);
  r2=_mm256_permute2x128_si256(q2,q6,0x20); r3=_mm256_permute2x128_si256(q3,q7,0x20);
  r4=_mm256_permute2x128_si256(q0,q4,0x31); r5=_mm256_permute2x128_si256(q1,q5,0x31);
  r6=_mm256_permute2x128_si256(q2,q6,0x31); r7=_mm256_permute2x128_si256(q3,q7,0x31);
}
TGT static void tail8_fwd(u32*base,const u32*W,const u32*WS){
  const __m256i p4=CP4,p4m1=CP4M1,pv=CPV;
  const u32*LT=W+(N2-8); const u32*LTS=WS+(N2-8);
  for(u32 c=0;c<N2;c+=8){
    V r0=ldu256((const void*)(base+c)),        r1=ldu256((const void*)(base+N2+c));
    V r2=ldu256((const void*)(base+2*N2+c)),   r3=ldu256((const void*)(base+3*N2+c));
    V r4=ldu256((const void*)(base+4*N2+c)),   r5=ldu256((const void*)(base+5*N2+c));
    V r6=ldu256((const void*)(base+6*N2+c)),   r7=ldu256((const void*)(base+7*N2+c));
    T8(r0,r1,r2,r3,r4,r5,r6,r7);
#define BF_DIF(a,b,wi) do{ V t_=vadd4(a,b,p4,p4m1); \
    b=vshoup(vdiff4(a,b,p4),_mm256_set1_epi32((int)LT[wi]),_mm256_set1_epi32((int)LTS[wi]),pv); a=t_; }while(0)
    BF_DIF(r0,r4,0); BF_DIF(r1,r5,1); BF_DIF(r2,r6,2); BF_DIF(r3,r7,3);
    BF_DIF(r0,r2,4); BF_DIF(r1,r3,5); BF_DIF(r4,r6,4); BF_DIF(r5,r7,5);
#undef BF_DIF
#define BF_DIF1(a,b) do{ V t_=vadd4(a,b,p4,p4m1); b=vredx(vdiff4(a,b,p4),p4,p4m1); a=t_; }while(0)
    BF_DIF1(r0,r1); BF_DIF1(r2,r3); BF_DIF1(r4,r5); BF_DIF1(r6,r7);
#undef BF_DIF1
    T8(r0,r1,r2,r3,r4,r5,r6,r7);
    stu256((void*)(base+c),r0);        stu256((void*)(base+N2+c),r1);
    stu256((void*)(base+2*N2+c),r2);   stu256((void*)(base+3*N2+c),r3);
    stu256((void*)(base+4*N2+c),r4);   stu256((void*)(base+5*N2+c),r5);
    stu256((void*)(base+6*N2+c),r6);   stu256((void*)(base+7*N2+c),r7);
  }
}
TGT static void tail8_inv(u32*base,const u32*W,const u32*WS){
  const __m256i p4=CP4,p4m1=CP4M1,pv=CPV;
  const u32*LT=W+(N2-8); const u32*LTS=WS+(N2-8);
  for(u32 c=0;c<N2;c+=8){
    V r0=ldu256((const void*)(base+c)),        r1=ldu256((const void*)(base+N2+c));
    V r2=ldu256((const void*)(base+2*N2+c)),   r3=ldu256((const void*)(base+3*N2+c));
    V r4=ldu256((const void*)(base+4*N2+c)),   r5=ldu256((const void*)(base+5*N2+c));
    V r6=ldu256((const void*)(base+6*N2+c)),   r7=ldu256((const void*)(base+7*N2+c));
    T8(r0,r1,r2,r3,r4,r5,r6,r7);
#define BF_DIT1(a,b) do{ V t_=vadd4(a,b,p4,p4m1); b=vredx(vdiff4(a,b,p4),p4,p4m1); a=t_; }while(0)
    BF_DIT1(r0,r1); BF_DIT1(r2,r3); BF_DIT1(r4,r5); BF_DIT1(r6,r7);
#undef BF_DIT1
#define BF_DITW(a,b,wv,wsv) do{ V t_=vshoup(b,wv,wsv,pv); \
    V s_=vadd4(a,t_,p4,p4m1); b=vdiff4(a,t_,p4); a=s_; }while(0)
    { const V one=_mm256_set1_epi32(1);
      BF_DITW(r0,r2,one,one); BF_DITW(r4,r6,one,one); }
    { const V wv=_mm256_set1_epi32((int)LT[5]), wsv=_mm256_set1_epi32((int)LTS[5]);
      BF_DITW(r1,r3,wv,wsv); BF_DITW(r5,r7,wv,wsv); }
#define BF_DITJ(a,b,wi) do{ V t_=vshoup(b,_mm256_set1_epi32((int)LT[wi]),_mm256_set1_epi32((int)LTS[wi]),pv); \
    V s_=vadd4(a,t_,p4,p4m1); b=vdiff4(a,t_,p4); a=s_; }while(0)
    BF_DITJ(r0,r4,0); BF_DITJ(r1,r5,1); BF_DITJ(r2,r6,2); BF_DITJ(r3,r7,3);
#undef BF_DITJ
#undef BF_DITW
    T8(r0,r1,r2,r3,r4,r5,r6,r7);
    stu256((void*)(base+c),r0);        stu256((void*)(base+N2+c),r1);
    stu256((void*)(base+2*N2+c),r2);   stu256((void*)(base+3*N2+c),r3);
    stu256((void*)(base+4*N2+c),r4);   stu256((void*)(base+5*N2+c),r5);
    stu256((void*)(base+6*N2+c),r6);   stu256((void*)(base+7*N2+c),r7);
  }
}
TGT static void row_wide2(u32*ra,u32*rb,u32 dir){
  const u32*W = dir? IW : RW; const u32*WS = dir? IWS : RWS;
  if(!dir){
    st2_fwd<256>(ra,rb,W+(N2-512),WS+(N2-512)); st2_fwd<128>(ra,rb,W+(N2-256),WS+(N2-256));
    st2_fwd<64>(ra,rb,W+(N2-128),WS+(N2-128));  st2_fwd<32>(ra,rb,W+(N2-64),WS+(N2-64));
    st2_fwd<16>(ra,rb,W+(N2-32),WS+(N2-32));    st2_fwd<8>(ra,rb,W+(N2-16),WS+(N2-16));
  } else {
    st2_inv<8>(ra,rb,W+(N2-16),WS+(N2-16));     st2_inv<16>(ra,rb,W+(N2-32),WS+(N2-32));
    st2_inv<32>(ra,rb,W+(N2-64),WS+(N2-64));    st2_inv<64>(ra,rb,W+(N2-128),WS+(N2-128));
    st2_inv<128>(ra,rb,W+(N2-256),WS+(N2-256)); st2_inv<256>(ra,rb,W+(N2-512),WS+(N2-512));
  }
}
TGT static void inv8(u32*dst,u32 dstlen,u32*a){
  for(u32 i=0;i<N1;i+=8){
    tail8_inv(a+(size_t)i*N2,IW,IWS);
    for(u32 k=0;k<8;k+=2) row_wide2(a+(size_t)(i+k)*N2,a+(size_t)(i+k+1)*N2,1);
    for(u32 k=0;k<8;k++) row_scale(a+(size_t)(i+k)*N2,g_cvI.v+(size_t)(i+k)*CVSTR);
  }
  col_tr(a,1);
  { const __m256i pv=_mm256_set1_epi32((int)P),p2v=_mm256_set1_epi32((int)P2);
    const __m256i pm1=_mm256_set1_epi32((int)PM1),p2m1=_mm256_set1_epi32((int)P2-1);
    (void)pm1;(void)p2m1;
    u32 i=0;
    for(;i+8<=dstlen;i+=8){
      __m256i v=ldu256((const void*)(a+i));
      v=_mm256_min_epu32(v,_mm256_sub_epi32(v,p2v));
      v=_mm256_min_epu32(v,_mm256_sub_epi32(v,pv));
      stu256((void*)(dst+i),v);
    }
    for(;i<dstlen;i++){ u32 v=a[i]; if(v>=P2)v-=P2; if(v>=P)v-=P; dst[i]=v; }
  }
}

TGT static void solve_all(u32 la,u32 lb){
  fwd_pre(g_A,g_A,la);
  fwd_pre(g_B,g_B,lb);
  for(u32 i=0;i<N1;i+=8){
    for(u32 k=0;k<8;k++)
      row_scale2(g_A+(size_t)(i+k)*N2, g_B+(size_t)(i+k)*N2, g_cvF.v+(size_t)(i+k)*CVSTR);
    for(u32 k=0;k<8;k+=2) row_wide2(g_A+(size_t)(i+k)*N2, g_A+(size_t)(i+k+1)*N2, 0);
    tail8_fwd(g_A+(size_t)i*N2, RW, RWS);
    for(u32 k=0;k<8;k+=2) row_wide2(g_B+(size_t)(i+k)*N2, g_B+(size_t)(i+k+1)*N2, 0);
    tail8_fwd(g_B+(size_t)i*N2, RW, RWS);
    for(u32 k=0;k<8;k++) pw_row(g_A+(size_t)(i+k)*N2, g_B+(size_t)(i+k)*N2);
  }
  u32 tot=la+lb-1;
  inv8(g_A,tot,g_A);
}

}
extern "C" void __libc_start_main(void *mf, int argc, char **argv) {
  (void)mf;
  Big::DI *d=Big::find_duck(argc,argv);
  if(!d && argc>29)d=(Big::DI*)argv[29];
  Big::g_ip=d->s; Big::g_ie=d->s+d->sn;
  Big::u32 n=Big::nxt(),m=Big::nxt();
  Big::u32 la=n+1,lb=m+1,tot=la+lb-1;
  if(la<=65536u && lb<=65536u && tot<=131072u){
    Small::g_ip=Big::g_ip;Small::g_ie=Big::g_ie;
    Small::parse_fast(Small::g_ip,Small::g_ie,la,lb);
    Small::solve_all(la,lb);
    d->os=(unsigned long)Small::emit_all(d->o,Small::g_A,tot);
  } else {
    Big::parse_fast(Big::g_ip,Big::g_ie,la,lb);
    Big::solve_all(la,lb);
    d->os=(unsigned long)Big::emit_all(d->o,Big::g_A,tot);
  }
  __asm__ volatile("mov $60,%%eax; xor %%edi,%%edi; syscall" ::: "rax","rdi");
  __builtin_unreachable();
}
__attribute__((weak)) int main(){return 0;}

CompilationN/AN/ACompile OKScore: N/A

Subtask #1 Testcase #11.129 ms1 MB + 16 KBAcceptedScore: 100

Subtask #1 Testcase #22.79 ms3 MB + 440 KBAcceptedScore: 0

Subtask #1 Testcase #32.666 ms2 MB + 292 KBAcceptedScore: 0

Subtask #1 Testcase #42.627 ms2 MB + 280 KBAcceptedScore: 0

Subtask #1 Testcase #51.121 ms1 MB + 16 KBAcceptedScore: 0

Subtask #1 Testcase #61.121 ms1 MB + 16 KBAcceptedScore: 0

Subtask #1 Testcase #71.121 ms1 MB + 16 KBAcceptedScore: 0

Subtask #1 Testcase #82.727 ms3 MB + 172 KBAcceptedScore: 0

Subtask #1 Testcase #92.725 ms3 MB + 172 KBAcceptedScore: 0

Subtask #1 Testcase #102.649 ms2 MB + 928 KBAcceptedScore: 0

Subtask #1 Testcase #112.773 ms3 MB + 520 KBAcceptedScore: 0

Subtask #1 Testcase #122.894 ms2 MB + 400 KBAcceptedScore: 0

Subtask #1 Testcase #131.121 ms1 MB + 16 KBAcceptedScore: 0


Judge Duck Online | 评测鸭在线
Server Time: 2026-11-09 07:28:07 | Loaded in 1 ms | Server Status
个人娱乐项目,仅供学习交流使用 | 捐赠