社区讨论

WA85求调

P15343「RedStone OI R1 C」Super Fib参与者 6已保存回复 16

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
16 条
当前快照
1 份
快照标识符
@mlnuu5ht
此快照首次捕获于
2026/02/15 22:42
4 天前
此快照最后确认于
2026/02/16 19:08
3 天前
查看原帖
挂且仅挂了 Sub3 所有点是何意味啊。。。。。。
CPP
#include <stdio.h>
#include <immintrin.h>
#pragma GCC target("avx2")

typedef __m256i m256i; 
typedef unsigned uint;
typedef unsigned long long ull;

uint P, Pinv, R, R2;

inline 
void init() {
	uint x = P & 1;
	x *= 2u - P * x;
	x *= 2u - P * x;
	x *= 2u - P * x;
	x *= 2u - P * x;
	x *= 2u - P * x;
	Pinv = -x;
	R = (1llu << 32) % P, R2 = (ull)R * R % P;
}

inline uint redc(ull t) { return (t + ull((uint)t * Pinv) * P) >> 32; }
inline uint mul(uint x, uint y) { return redc((ull)x * y); }
inline uint toMont(uint x) { return mul(x, R2); }
inline uint fromMont(uint x) { return x = redc(x), x < P ? x : x - P; }
inline uint add(uint x, uint y) { return x += y, x >= P ? x - P : x; }
inline uint sub(uint x, uint y) { return x < y ? x + P - y : x - y; }

inline 
m256i add(m256i x, m256i y) {
	m256i s = _mm256_add_epi32(x, y);
	m256i d = _mm256_sub_epi32(s, _mm256_set1_epi32(P));
	return _mm256_min_epu32(s, d);
}

inline 
m256i redc(m256i x) {
	m256i m = _mm256_mul_epu32(x, _mm256_set1_epi32(Pinv));
	m256i v = _mm256_mul_epu32(m, _mm256_set1_epi32(P));
	return _mm256_add_epi64(x, v);
}

inline 
m256i mul(m256i x, m256i y) {
	m256i x1 = _mm256_shuffle_epi32(x, 0xF5);
	m256i y1 = _mm256_shuffle_epi32(y, 0xF5);
	m256i res0 = redc(_mm256_mul_epu32(x, y));
	m256i res1 = redc(_mm256_mul_epu32(x1, y1));
	res0 = _mm256_shuffle_epi32(res0, 0xF5);
	return _mm256_blend_epi32(res0, res1, 0xAA);
}

typedef m256i vec;

inline 
void sqr_mat(const auto __restrict__ a, auto __restrict__ res) {
	for (int i = 0; i < 8; i++) *(m256i *)res[i] = _mm256_set1_epi32(0);
    for (int i = 0; i < 8; i++) {
    	for (int k = 0; k < 8; k++) {
            if (a[i][k]) *(m256i *)res[i] = add(mul(_mm256_set1_epi32(a[i][k]), *(m256i *)a[k]), *(m256i *)res[i]);
        }
	}
}

inline 
void mul_vec(const uint* __restrict__ a, const auto __restrict__ b, uint* __restrict__ res) {
	*(m256i *)res = _mm256_set1_epi32(0);
    for (int k = 0; k < 8; k++) {
        if (a[k]) *(m256i *)res = add(mul(_mm256_set1_epi32(a[k]), *(m256i *)b[k]), *(m256i *)res);
    }
}


alignas(32) uint f[8][8], g[8][8], res[8], tmp[8];

inline 
void qpow(ull n) {
	for (; ; ) {
		if (n & 1) mul_vec(res, f, tmp), *(m256i *)res = *(m256i *)tmp;
		n >>= 1; if (!n) break; sqr_mat(f, g);
		for (int j = 0; j < 8; j++) *(m256i *)f[j] = *(m256i *)g[j];
	}
}

int T; uint a, b, c, p, q; ull n; 

int main() {
	for (scanf("%d", &T); T--; ) {
		scanf("%u%u%u%u%u%llu%u", &a, &b, &c, &p, &q, &n, &P), init();
		a %= P, b %= P, c %= P, p %= P, q %= P;
		*(m256i *)res = _mm256_set_epi32(0, 0, toMont(1 % P), toMont(1 % P), toMont(1 % P), toMont(c), toMont(b), toMont(a));
		ull nx = (n - 1) / 3, ny = n % 3;
		if (nx) {
			uint i1 = toMont(1 % P), i3 = toMont(3 % P), i6 = toMont(6 % P), i7 = toMont(7 % P), i9 = toMont(9 % P);
			uint i11 = toMont(11 % P), i12 = toMont(12 % P), i20 = toMont(20 % P), i30 = toMont(30 % P);
			p = toMont(p), q = toMont(q);
			uint p2 = mul(p, p), x = add(p2, q), y = add(mul(i7, p), i9), z = add(p, i1), w = add(mul(i12, p), i20);
			uint tx = mul(p, x), ty = add(mul(p, y), i11), tz = add(mul(p, z), i1), tw = add(mul(p, w), i30);
			*(m256i *)f[0] = _mm256_set_epi32(0, i1, 0, 0, 0, mul(p2, q), mul(p, q), q);
			*(m256i *)f[1] = _mm256_set_epi32(0, i1, 0, 0, 0, q, 0, 0);
			*(m256i *)f[2] = _mm256_set_epi32(0, i1, 0, 0, 0, tx, x, p);
			*(m256i *)f[3] = _mm256_set_epi32(0, 0, 0, i6, i1, ty, y, i7);
			*(m256i *)f[4] = _mm256_set_epi32(0, 0, 0, i1, 0, tz, z, i1);
			*(m256i *)f[5] = _mm256_set_epi32(0, 0, i1, i9, i3, tw, w, i12);
			*(m256i *)f[6] = _mm256_set_epi32(0, i1, 0, 0, 0, 0, 0, 0);	
			*(m256i *)f[7] = _mm256_set_epi32(0, 0, 0, 0, 0, 0, 0, 0);
			qpow(nx);
		}
		uint ans = add(res[0], res[6]);
		if (~ny & 1) ans = add(ans, res[1]);
		if (!ny) ans = add(ans, res[2]);
		printf("%u\n", fromMont(ans));
	}
}

回复

16 条回复,欢迎继续交流。

正在加载回复...