ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

2021.9.21 乘法

2021-10-30 16:31:10  阅读:143  来源: 互联网

标签:return log 2021.9 define times vis int 乘法 21


2021.9.21 乘法

原题目可以转换为求\(f(n!)\equiv x\pmod {2^{64}}\)中的\(x\)

其中\(f(x)\)表示满足\(v\mid x\)且\(2\nmid v\)的最大的\(v\)

由于任意正整数可以写成\(p\times 2^k(2\nmid p)\)

我们考虑计算\(k\)相同的数的乘积,最后再乘起来

对于\(X100...0\)(二进制,后有\(k\)个0),我们想求的就是所有\(X1\)的乘积

即要求\(1\times 3\times 5...\times (2v+1)\)

我们可以构造多项式\(g_v(x)=\prod_{i=1}^v (2x+2i+1)\)

使用倍增的思想,设\(o=\lfloor\frac{v}{2}\rfloor\),我们可以先算出\(g_o(x)\)

则\(g_v(x)=g_o(x)g_o(x+o)\)(零头补上即可)

使用多项式平移的技巧,使用\(O(len^2)\)的暴力卷积g_o可以计算

多项式平移:

\[\begin{aligned}f(x+v)&=\sum_{i=0}^na_i(x+v)^i\\&=\sum_{i=0}^na_i\sum_{j=0}^iv^j{i\choose j}x^{i-j}\\\end{aligned} \]

这样便在\(O(n\log n/n^2)\)内实现了变量的加值

我们发现\(2^n\mid[x^n]g_v(x)\)

所以这个多项式实际上不超过\(63\)次

每次都这样做时间复杂度为\(O(T\log^4n)\)

我们发现在枚举\(2^k\)时和倍增的过程是相同的,合并倍增与枚举\(k\)即可做到\(O(T\log^3n)\)

闲着没事的话也可以做到\(O(T\log^2n\log\log n)\)(不建议)

当然还需要在最后算出\(2^k\)对答案的贡献

#include<bits/stdc++.h>
using namespace std;
# define ll long long
# define read read1<ll>()
# define Type template<typename T>
Type T read1(){
	T t=0;
	char k;
	bool vis=0;
	do (k=getchar())=='-'&&(vis=-1);while('0'>k||k>'9');
	while('0'<=k&&k<='9')t=(t<<3)+(t<<1)+(k^'0'),k=getchar();
	return vis?-t:t;
}
# define fre(k) freopen(k".in","r",stdin);freopen(k".out","w",stdout)
# define ull unsigned ll
ull C[70][70];
char ret(int x){return x<10?x+'0':x-10+'A';}
ull qkpow(ull x,ull y){
	ull t=1;
	for(;y;y>>=1,x*=x)
		if(y&1)t*=x;
	return t;
}
# define A vector<ull>
A sol(ull x){
	A t;
	if(x==1){
		t.push_back(3);
		t.push_back(2);
		return t;
	}
	ull mid=x>>1;
	A u,v;
	u=sol(mid);
	for(int i=0;i<u.size();++i){
		v.push_back(0);ull r=1;
		for(int j=0;j<=i;++j){
			v[i-j]+=u[i]*C[i][j]*r;
			r*=mid;
		}
	}int n=min(70,(int)(u.size()+v.size()-1+(x&1)));
	t.resize(n);for(int i=0;i<n;++i)t[i]=0;
	for(int i=0;i<u.size();++i)
		for(int j=0;i+j<n&&j<v.size();++j)
			t[i+j]+=u[i]*v[j];
	if(x&1){
		ull p=x<<1|1u;
		for(int i=t.size();--i;)t[i]=t[i-1]*2+t[i]*p;
		t[0]*=p;
	}
//	if(t.size()>64)assert(!t[64]);
	return t;
}
int main(){fre("multiplication");
	for(int i=0;i<70;++i){
		C[i][0]=C[i][i]=1;
		for(int j=1;j<i;++j)
			C[i][j]=C[i-1][j]+C[i-1][j-1];
	}
	for(int T=read;T--;){
		ull t=1,h=0,s;
		scanf("%llu",&s);
		for(int i=0;i<64;++i){
			ull x=s>>i;
			if(x&1)x>>=1;
			else if(x)x=x-1u>>1;
			if(x)t*=sol(x)[0];
		}
		for(int i=1;i<64;++i)
			(h+=s>>i)&=3u;
		t<<=h;
		bool vis=0;
		for(int i=16;i--;){
			char k=ret((t>>i*4)&15);
			if(k!='0'||vis)putchar(k),vis=1;
		}if(!vis)putchar('0');putchar('\n');
	}
	return 0;
}

标签:return,log,2021.9,define,times,vis,int,乘法,21
来源: https://www.cnblogs.com/SYDevil/p/15485370.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有