所以,到底怎么卡过去啊
查看原帖
所以,到底怎么卡过去啊
246331
mystic_qwq楼主2024/7/29 09:56
#include <immintrin.h>
#include <stdio.h>
#pragma GCC target("avx2")
#define U unsigned
#define LL long long
#define ULL unsigned long long
#define S static
#define MI __m256i
#define IL inline
#define ADD _mm256_add_epi32
#define SUB _mm256_sub_epi32
#define CMP _mm256_cmpgt_epi32
#define AND _mm256_and_si256
#define MUL _mm256_mul_epu32
#define SRLI1 _mm256_srli_epi64
#define SRLI2 _mm256_srli_si256
#define ADD1 _mm256_add_epi64
#define OR _mm256_or_si256
#define ZERO _mm256_setzero_si256
#define SET _mm256_set_epi32
#define SET1 _mm256_set1_epi32
#define M mon_in
S U mod, r, n2_;
S MI a0, mod1, R, hi32, ans, ml, ad;
LL exgcd(LL a, LL b, LL& x, LL& y) {
  if (b == 0) {
    x = 1;
    y = 0;
    return a;
  }
  LL gcd = exgcd(b, a % b, y, x);
  y -= a / b * x;
  return gcd;
}
U IL mul(U x, U y) {
  ULL z = (ULL)x * y;
  return (z + (ULL)((U)z * r) * mod) >> 32;
}
IL MI add(MI x, MI y) {
  MI apb = ADD(x, y), ret = SUB(apb, mod1);
  MI cmp = CMP(a0, ret), add = AND(cmp, mod1);
  return ADD(add, ret);
}
IL MI mul(MI x, MI y) {
  MI z = x, w, p = y;
  y = MUL(x, y);
  x = MUL(MUL(y, R), mod1);
  w = SRLI1(ADD1(x, y), 32);  //
  x = SRLI2(z, 4);
  y = SRLI2(p, 4);
  y = MUL(x, y);
  x = MUL(MUL(y, R), mod1);
  x = AND(ADD1(x, y), hi32);  //
  return OR(x, w);
}
IL U mon_in(U x) {
  return mul(x, n2_);
}
IL U mon_out(U x) {
  U ret = ((x + (ULL)((U)x * r) * mod) >> 32);
  return ret < mod ? ret : ret - mod;
}
void solve(int n, int p) {
  U i = 1;
  LL x, y;
  mod = p;
  n2_ = -(ULL)mod % mod;
  exgcd(mod, 1ll << 32, x, y);
  r = -(U)x;  //
  a0 = ZERO();
  mod1 = SET1(mod);
  R = SET1(r);
  hi32 = SET(-1, 0, -1, 0, -1, 0, -1, 0);
  ans = SET1(M(1));
  ad = SET1(M(8));
  ml = SET(M(8), M(7), M(6), M(5), M(4), M(3), M(2), M(1));
  for (; i + 8 <= n; i += 8) {// 这里
    ans = mul(ans, ml);
    ml = add(ml, ad);
  }
  U* fl = (U*)&ans;
  U as = mul(mul(mul(fl[0], fl[1]), mul(fl[2], fl[3])),
             mul(mul(fl[4], fl[5]), mul(fl[6], fl[7])));
  as = mon_out(as);
  for (; i <= n; ++i)
    as = 1ull * as * i % mod;
  printf("%u\n", as);
}
main(int T) {
  scanf("%d", &T);
  while (T--) {
    int n, p;
    scanf("%d%d", &n, &p);
    solve(n, p);
  }
}

这里又在题解基础上加了循环展开,只快了 0.03s 崩不住了(求助大佬真难卡

2024/7/29 09:56
加载中...