[ACNOI2021]与多项式无关的题

题目

题目描述
n ! n! n! 转成十六进制后,去掉末尾的零的最后 16 16 16 位。

数据范围与提示
n < 2 64 n<2^{64} n<264,共 10 10 10 组数据。

思路

显然只需要除掉 2 2 2,就可以去除末尾的零。根据 2 2 2 的次数模 4 4 4 的结果,可以补上后面存在的零,所以问题只在于求出
∏ 2 i + 1 ⩽ n ( 2 i + 1 ) \prod_{2i+1\leqslant n}(2i+1) 2i+1n(2i+1)
然后递归 ⌊ n 2 ⌋ \lfloor{n\over 2}\rfloor 2n 即可。考虑到 n n n 的范围,上面这玩意儿肯定考虑倍增。当知道 ∑ T ⫅ S ∣ T ∣ = i ( ∏ x ∈ T x ) \sum_{T\subseteqq S}^{|T|=i}\left(\prod_{x\in T}x\right) TST=i(xTx) 时,可以很轻易地求出 ∑ T ⫅ S ∣ T ∣ = i [ ∏ x ∈ T ( x + v ) ] \sum_{T\subseteqq S}^{|T|=i}\left[\prod_{x\in T} (x+v)\right] TST=i[xT(x+v)] 的结果,即枚举 v v v 的次数。类似地,我们也可以将两个集合 S 1 , S 2 S_1,S_2 S1,S2 合并为 S S S 的同时维护这个结果。

取模 2 64 2^{64} 264 肯定是突破口。考虑 v = 2 p v=2^p v=2p,那么 v v v 的次数超过 ⌊ 64 p ⌋ \lfloor\frac{64}{p}\rfloor p64 时,一切都失去了意义。所以我们只需要存储 ∣ T ∣ ⩾ ∣ S ∣ − 64 |T|\geqslant|S|-64 TS64 的值,上面两个操作都是 O ( B 2 ) \mathcal O(B^2) O(B2) 的,其中 B = 64 B=64 B=64

那么,把 S p = { 1 , 3 , 5 , … , 2 p − 1 } S_p=\{1,3,5,\dots,2^p-1\} Sp={1,3,5,,2p1} 的结果预处理出来,然后可以用 S p S_p Sp x x x 加上 2 q    ( q < p ) 2^q\;(q<p) 2q(q<p) 再与 S q S_q Sq 并起来,得到 S = { 1 , 3 , 5 , … , 2 p + 2 q − 1 } S=\{1,3,5,\dots,2^{p}+2^{q}-1\} S={1,3,5,,2p+2q1} 。所以就用这招,可以 O ( B 3 ) \mathcal O(B^3) O(B3) 的得到任意 n n n 的结果。

再加上外层的 O ( B ) \mathcal O(B) O(B) 递归,复杂度 O ( B 4 ) \mathcal O(B^4) O(B4) 。算出来就感觉过不了,然后它过了……本机测试也跑得非常快……

听了 H a n d I n D e v i l \sf HandInDevil HandInDevil 一席话,发觉这实际上有一个 多项式 的背景。考虑记 F ( x ) = ∏ 1 ⩽ 2 i + 1 ⩽ n ( x + 2 i + 1 ) F(x)=\prod_{1\leqslant 2i+1\leqslant n}(x+2i+1) F(x)=12i+1n(x+2i+1),那么代入任意 2 ∣ x 2\mid x 2x 时,都只需计算 x B − 1 x^{B-1} xB1 以内的几项。(这和 ∣ T ∣ ⩾ ∣ S ∣ − B |T|\geqslant |S|-B TSB 的含义是相同的。)

而且多项式做上面的操作,可以做到 O ( B log ⁡ B ) \mathcal O(B\log B) O(BlogB)只是没人这么写。并且直接将 x x x 代入,就是 O ( B ) \mathcal O(B) O(B) 计算。所以一层的复杂度可以做到 O ( B 2 ) \mathcal O(B^2) O(B2),总复杂度 O ( B 3 ) \mathcal O(B^3) O(B3)

代码

能过的代码为什么要改进呢,给自己搞一堆锅出来

#include <cstdio>
#include <iostream>
#include <vector>
#include <cstring>
#include <algorithm>
#include <cctype>
using namespace std;
# define rep(i,a,b) for(int i=(a); i<=(b); ++i)
# define drep(i,a,b) for(int i=(a); i>=(b); --i)
typedef unsigned long long int_;
inline int readint(){
	int a = 0, c = getchar(), f = 1;
	for(; !isdigit(c); c=getchar())
		if(c == '-') f = -f;
	for(; isdigit(c); c=getchar())
		a = (a<<3)+(a<<1)+(c^48);
	return a*f;
}
inline int_ readLong(){
	int_ a = 0; int c = getchar();
	for(; !isdigit(c); c=getchar());
	for(; isdigit(c); c=getchar())
		a = (a<<3)+(a<<1)+(c^48);
	return a;
}
void writeHex(int_ x){
	static const char HEX_DIGIT[] = "0123456789ABCDEF";
	if(x>>4) writeHex(x>>4);
	putchar(HEX_DIGIT[x&15]);
}

const int BASE = 64;
int_ c[BASE][BASE]; // combination
struct Node{
	int_ val[BASE]; ///< index: how many UNCHOSEN
	/// @brief consider every integers plus ( 1 << @p n )
	void shift(int n){
		for(int i=1; i<BASE; ++i){
			int_ v = 1; // ratio
			for(int j=i-1; ~j; --j){
				if((v <<= n) == 0) break;
				val[j] += c[i][j]*v*val[i];
			}
		}
	}
	void operator *= (const Node &t){
		for(int i=BASE-1; ~i; --i){
			for(int j=1; j+i<BASE; ++j)
				val[i+j] += val[i]*t.val[j];
			val[i] *= t.val[0];
		}
	}
};

Node xez[BASE];
int_ solve(int_ n){
	bool f = bool(n&1);
	Node ans = xez[0]; // empty set
	for(int_ x=n-f; x; ){
		int d = 63-__builtin_clzll(x);
		ans.shift(d); ans *= xez[d];
		x ^= (int_(1)<<d); // remove
	}
	int_ xyx = ans.val[0];
	return f ? (xyx*n) : xyx;
}

int main(){
	freopen("multiplication.in","r",stdin);
	freopen("multiplication.out","w",stdout);
	rep(i,0,BASE-1){
		c[i][0] = 1; // unsigned long long
		rep(j,1,i) c[i][j] = c[i-1][j-1]+c[i-1][j];
	}
	xez[0].val[0] = 1; // truly empty
	xez[1].val[0] = xez[1].val[1] = 1; // when n = 2
	rep(i,2,BASE-1){
		xez[i] = xez[i-1]; xez[i].shift(i-1);
		xez[i] *= xez[i-1];
	}
	for(int T=readint(); T; --T){
		int_ n = readLong(), res = 1;
		unsigned char p = 0;
		for(; n; n>>=1){
			res *= solve(n);
			p = char((p+(n>>1))&3);
		}
		writeHex(res<<p), putchar('\n');
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值