提交记录 21835


用户 题目 状态 得分 用时 内存 语言 代码长度
zhangbo1000 1004a. 【模板题】高精度乘法2 Accepted 100 442.81 us 216 KB C++14 9.37 KB
提交时间 评测时间
2024-06-03 12:48:49 2024-06-03 12:48:52
#include<cstring>
#include<cmath>
#include<vector>
#include<iostream>
#include<iomanip>
namespace FFT{
	//complex numbers
	using size_t=unsigned int;
	class complex{
		double a,b;
	public:
		complex(const complex& x):a(x.a),b(x.b){}
		complex(){}
		constexpr complex(const double& x,const double& y):a(x),b(y){}
		complex(const double& x):a(x),b(0){}
		const complex operator=(const double& x){return a=x;}
		const complex operator=(const complex& x){
			a=x.a;b=x.b;
			return *this;
		}
		const complex operator+(const complex& x)const{
			return complex(a+x.a,b+x.b);
		}
		const complex operator-(const complex& x)const{
			return complex(a-x.a,b-x.b);
		}
		const complex operator*(const complex& x)const{
			return complex(a*x.a-b*x.b,a*x.b+b*x.a);
		}
		const complex operator+=(const complex& x){
			a+=x.a;
			b+=x.b;
			return *this;
		}
		const complex operator-=(const complex& x){
			a-=x.a;
			b-=x.b;
			return *this;
		}
		const complex operator*=(const complex& x){
			return (*this)=(*this)*x;
		}
		double real()const{return a;}
		double imag()const{return b;}
		double real(const double& x){return a=x;}
		double imag(const double& x){return b=x;}
	};
	//Fast Fourier Transform
	using cp=complex;
	constexpr double pi=acos(-1),pi2=2*acos(-1),pi6=6*acos(-1);
	template<const size_t n>
	void dif(cp a[]){
		constexpr size_t half=n>>1,quarter=n>>2;
		cp w(1,0),w3(1,0);
		const cp wn(cos(pi2/n),sin(pi2/n)),wn3(cos(pi6/n),sin(pi6/n));
		for(size_t i=0;i<quarter;i++){
			if(!(i&31))w=cp(cos(pi2*i/n),sin(pi2*i/n)),w3=cp(cos(pi6*i/n),sin(pi6*i/n));
			const cp tmp1=a[i],tmp2=a[i+quarter],tmp3=a[i+half],tmp4=a[i+half+quarter];
			cp x=tmp1-tmp3,y=tmp2-tmp4;
			y=cp(y.imag(),-y.real());
			a[i]+=tmp3;
			a[i+quarter]+=tmp4;
			a[i+half]=(x-y)*w;
			a[i+half+quarter]=(x+y)*w3;
			w*=wn;
			w3*=wn3;
		}
		dif<half>(a);
		dif<quarter>(a+half);
		dif<quarter>(a+half+quarter);
	}
	template<>
	void dif<1>(cp a[]){}
	template<>
	void dif<0>(cp a[]){}
	template<>
	void dif<2>(cp a[]){
		const cp x=a[0],y=a[1];
		a[0]+=y;
		a[1]=x-y;
	}
	void rundif(cp a[],const size_t& n){
		switch (n) {
			case 1<<1:dif<1<<1>(a);break;
			case 1<<2:dif<1<<2>(a);break;
			case 1<<3:dif<1<<3>(a);break;
			case 1<<4:dif<1<<4>(a);break;
			case 1<<5:dif<1<<5>(a);break;
			case 1<<6:dif<1<<6>(a);break;
			case 1<<7:dif<1<<7>(a);break;
			case 1<<8:dif<1<<8>(a);break;
			case 1<<9:dif<1<<9>(a);break;
			case 1<<10:dif<1<<10>(a);break;
			case 1<<11:dif<1<<11>(a);break;
			case 1<<12:dif<1<<12>(a);break;
			case 1<<13:dif<1<<13>(a);break;
			case 1<<14:dif<1<<14>(a);break;
			case 1<<15:dif<1<<15>(a);break;
			case 1<<16:dif<1<<16>(a);break;
			case 1<<17:dif<1<<17>(a);break;
			case 1<<18:dif<1<<18>(a);break;
			case 1<<19:dif<1<<19>(a);break;
			case 1<<20:dif<1<<20>(a);break;
			case 1<<21:dif<1<<21>(a);break;
		}
	}
	template<const size_t n>
	void dit(cp a[]){
		constexpr size_t half=n>>1,quarter=n>>2;
		dit<half>(a);
		dit<quarter>(a+half);
		dit<quarter>(a+half+quarter);
		cp w(1,0),w3(1,0);
		const cp wn(cos(pi2/n),-sin(pi2/n)),wn3(cos(pi6/n),-sin(pi6/n));
		for(size_t i=0;i<quarter;i++){
			if(!(i&7))w=cp(cos(pi2*i/n),-sin(pi2*i/n)),w3=w*w*w;
			const cp tmp1=w*a[i+half],tmp2=w3*a[i+half+quarter];
			const cp x=a[i],y=tmp1+tmp2;
			cp x1=a[i+quarter],y1=tmp1-tmp2;
			y1=cp(y1.imag(),-y1.real());
			a[i]+=y;
			a[i+quarter]+=y1;
			a[i+half]=x-y;
			a[i+half+quarter]=x1-y1;
			w*=wn;
			w3*=wn3;
		}
	}
	template<>
	void dit<1>(cp a[]){}
	template<>
	void dit<0>(cp a[]){}
	template<>
	void dit<2>(cp a[]){
		const cp x=a[0],y=a[1];
		a[0]+=y;
		a[1]=x-y;
	}
	void rundit(cp a[],const size_t& n){
		switch (n) {
			case 1<<1:dit<1<<1>(a);break;
			case 1<<2:dit<1<<2>(a);break;
			case 1<<3:dit<1<<3>(a);break;
			case 1<<4:dit<1<<4>(a);break;
			case 1<<5:dit<1<<5>(a);break;
			case 1<<6:dit<1<<6>(a);break;
			case 1<<7:dit<1<<7>(a);break;
			case 1<<8:dit<1<<8>(a);break;
			case 1<<9:dit<1<<9>(a);break;
			case 1<<10:dit<1<<10>(a);break;
			case 1<<11:dit<1<<11>(a);break;
			case 1<<12:dit<1<<12>(a);break;
			case 1<<13:dit<1<<13>(a);break;
			case 1<<14:dit<1<<14>(a);break;
			case 1<<15:dit<1<<15>(a);break;
			case 1<<16:dit<1<<16>(a);break;
			case 1<<17:dit<1<<17>(a);break;
			case 1<<18:dit<1<<18>(a);break;
			case 1<<19:dit<1<<19>(a);break;
			case 1<<20:dit<1<<20>(a);break;
			case 1<<21:dit<1<<21>(a);break;
		}
	}
}
namespace Bigint{
	//unsigned long long long int
	class ulllint{
		friend std::istream;
		friend std::ostream;
		using size_t=unsigned int;
		using ll=size_t;
		static constexpr size_t len=5;
		static constexpr size_t base=100000;
		std::vector<ll>nums;
		std::vector<ll>::const_iterator begin()const{return nums.begin();}
		std::vector<ll>::const_iterator end()const{return nums.end();}
		size_t size()const{return nums.size();}
		ll& operator[](const size_t& x){return nums[x];}
		const ll& operator[](const size_t& x)const{return nums[x];}
		ulllint(const std::vector<ll>::const_iterator& first,const std::vector<ll>::const_iterator& last){
			nums=std::vector<ll>(first,last);
		}// 用 vector 构造。
		ulllint(const short& x,const ll& y){
			nums=std::vector<ll>(x,y);
		}// 用多个相同数构造,不处理进位。
		ulllint(const std::vector<ll>&x){nums=x;}
	public:
		//用整数构造
		ulllint(const size_t& x=0){
			nums=std::vector<ll>(1,x);
			int i=0;
			while(nums[i]>base)nums.push_back(nums[i]/base),nums[i++]%=base;
		}
		//复制
		ulllint(const ulllint& x){
			nums=x.nums;
		}
		ulllint& operator=(const ulllint& x){
			nums=x.nums;
			return *this;
		}
		static constexpr size_t MAX_SIZE=1000000;
		friend std::istream& operator>>(std::istream& cin,ulllint& x);
		friend std::ostream& operator<<(std::ostream& cout,const ulllint& x);
		friend ulllint operator+(const ulllint& x,const ulllint& y);
		friend ulllint operator-(const ulllint& x,const ulllint& y);
		friend ulllint operator*(const ulllint& x,const ulllint& y);
		friend ulllint operator/(const ulllint& x,const ulllint& y);
		ulllint operator+=(const ulllint& x){
			if(x.size()>size()){
				nums.resize(x.size()+1);
			}
			for(size_t i=0;i<size();i++){
				nums[i]+=x[i];
				nums[i+1]+=nums[i]/base;
				nums[i]%=base;
			}
			while((size()>1)&&nums[size()-1]==0)nums.pop_back();
			return *this;
		}
		ulllint operator-=(const ulllint& x){
			for(size_t i=0;i<x.size();i++){
				if(nums[i]<x[i]){
					nums[i+1]--;
					nums[i]+=base;
				}
				nums[i]-=x[i];
			}
			while(size()>1&&nums[size()-1]==0)nums.pop_back();
			return *this;
		}
		friend ulllint operator*=(ulllint& x,const ulllint& y);
		//	ulllint operator*=(const ulllint& x){(*this)=(*this)*x;return *(this);}
	};
	char temp[ulllint::MAX_SIZE+1];
	//输入输出,采用 iostream
	std::istream& operator>>(std::istream& cin,ulllint& x){
		std::cin>>temp;
		const size_t l=strlen(temp);
		size_t j=-1,w=1;
		x.nums.resize(l/ulllint::len+2);
		for(size_t i=0;i<l;i++){
			if(!(i%ulllint::len))j++,w=1;
			x[j]+=(temp[l-i-1]^'0')*w;
			w*=10;
		}
		while(x.size()>1&&x[x.size()-1]==0)x.nums.pop_back();
		return cin;
	}
	std::ostream& operator<<(std::ostream& cout,const ulllint& x){
		if(x.size()==0)return cout;
		cout<<x[x.size()-1];
		for(signed int i=((int)x.size())-2;i>=0;i--){
			cout<<std::setfill('0')<<std::setw(ulllint::len)<<x[i];
		}
		return cout;
	}
	ulllint operator+(const ulllint& x,const ulllint& y){
		if(x.size()==0)return y;
		if(y.size()==0)return x;
		ulllint c(std::max(x.size(),y.size())+1,0);
		for(size_t i=0;i<x.size();i++)c[i]+=x[i];
		for(size_t i=0;i<y.size();i++)c[i]+=y[i];
		for(size_t i=0;i<c.size()-1;i++)c[i+1]+=c[i]/ulllint::base,c[i]%=ulllint::base;
		while(c.size()>1&&c[c.size()-1]==0)c.nums.pop_back();
		return c;
	}
	ulllint operator-(const ulllint& x,const ulllint& y){
		if(y.size()==0)return x;
		ulllint z(x);
		for(size_t i=0;i<y.size();i++){
			if(z[i]<y[i]){
				z[i]+=ulllint::base;
				z[i+1]--;
			}
			z[i]-=y[i];
		}
		while(z.size()>1&&z[z.size()-1]==0)z.nums.pop_back();
		return z;
	}
	ulllint operator*(const ulllint& x,const ulllint& y){
		static FFT::cp tmp[ulllint::MAX_SIZE];
		static ulllint c;
		ulllint::size_t n=x.size()+y.size()-1,s=1;
		while(s<=n)s<<=1;
		c.nums.resize(s);
		for(ulllint::size_t i=std::max(x.size(),y.size());i<s;i++)tmp[i]=0; 
		for(ulllint::size_t i=0;i<x.size();i++)tmp[i].real(x[i]);
		for(ulllint::size_t i=0;i<y.size();i++)tmp[i].imag(y[i]);
		FFT::rundif(tmp,s);
		for(ulllint::size_t i=0;i<s;i++)tmp[i]*=tmp[i];
		FFT::rundit(tmp,s);
		const int kkk=s;
		const double change=0.5/kkk;
		unsigned long long int _tmp=0;
		for(ulllint::size_t i=0;i<s;i++){
			_tmp+=(unsigned long long int)((tmp[i].imag()*change)+0.5);
			c[i]=_tmp%ulllint::base;
			_tmp/=ulllint::base;
		}
		while(c.size()>1&&c[c.size()-1]==0)c.nums.pop_back();
		return c;
	}
	ulllint operator*=(ulllint& x,const ulllint& y){
		static FFT::cp tmp[ulllint::MAX_SIZE];
		ulllint::size_t n=x.size()+y.size()-1,s=1;
		while(s<=n)s<<=1;
		for(ulllint::size_t i=std::max(x.size(),y.size());i<s;i++)tmp[i]=0; 
		for(ulllint::size_t i=0;i<x.size();i++)tmp[i].real(x[i]);
		for(ulllint::size_t i=0;i<y.size();i++)tmp[i].imag(y[i]);
		FFT::rundif(tmp,s);
		for(ulllint::size_t i=0;i<s;i++)tmp[i]*=tmp[i];
		FFT::rundit(tmp,s);
		x.nums.resize(s);
		const int kkk=s;
		const double change=0.5/kkk;
		unsigned long long int _tmp=0;
		for(ulllint::size_t i=0;i<s;i++){
			_tmp+=(unsigned long long int)((tmp[i].imag()*change)+0.5);
			x[i]=_tmp%ulllint::base;
			_tmp/=ulllint::base;
		}
		while(x.size()>1&&x[x.size()-1]==0)x.nums.pop_back();
		return x;
	}
}
int main(){
	std::iostream::sync_with_stdio(0);
	Bigint::ulllint a,b;
	std::cin>>a>>b;
	a*=b;
	std::cout<<a;
	return 0;
}

CompilationN/AN/ACompile OKScore: N/A

Testcase #1442.81 us216 KBAcceptedScore: 100


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