QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#65718#3799. It's Surely Complexdlg#WA 4ms3384kbC++174.0kb2022-12-03 12:06:552022-12-03 12:06:57

Judging History

你现在查看的是最新测评结果

  • [2023-08-10 23:21:45]
  • System Update: QOJ starts to keep a history of the judgings of all the submissions.
  • [2022-12-03 12:06:57]
  • 评测
  • 测评结果:WA
  • 用时:4ms
  • 内存:3384kb
  • [2022-12-03 12:06:55]
  • 提交

answer

#if not _GLIBCXX_DEBUG
#define NDEBUG 1
#endif
#include<bits/stdc++.h>

namespace FFT{
int constexpr MOD=998244353;
struct M{
	int x;
	void operator+=(M o){ x+=o.x; if(x>=MOD) x-=MOD; }
	void operator-=(M o){ x-=o.x; if(x<0) x+=MOD; }
	void operator*=(M o){ x=int(int64_t(x)*o.x%MOD); }
	friend M operator+(M a,M b){ a+=b; return a; }
	friend M operator-(M a,M b){ a-=b; return a; }
	friend M operator*(M a,M b){ a*=b; return a; }
	M pow(int e)const{
		auto b=*this;
		M re{1};
		while(e){
			if(e&1) re*=b;
			e>>=1;
			b*=b;
		}
		return re;
	}
	M inv()const{
		return pow(MOD-2);
	}
};

void fft(std::vector<M>& a,bool invert){
	M const root{3};


	int n=int(a.size());
	assert((n&(n-1))==0);
	int lg=__builtin_ctz(n);
	for(int i=0;i<n;i++){
		int j=0;
		for(int k=0;k<lg;k++) if(i>>k&1) j|=1<<(lg-k-1);
		if(i<j) std::swap(a[i],a[j]);
	}
	for(int len=2;len<=n;len*=2){
		M wlen=root.pow((MOD-1)/len);
		if(invert) wlen=wlen.inv();
		for(int i=0;i<n;i+=len){
			M w{1};
			for(int j=0;j<len/2;j++){
				auto u=a[i+j];
				auto v=a[i+j+len/2]*w;
				a[i+j]=u+v;
				a[i+j+len/2]=u-v;
				w*=wlen;
			}
		}
	}
	if(invert){
		assert(n<MOD);
		auto mul=M{n}.inv();
		for(auto& x:a) x*=mul;
	}
}

[[nodiscard]] std::vector<M> mul(std::vector<M> a,std::vector<M> b){
	auto rlen=int(a.size()+b.size()-1);
	auto len=1; while(len<rlen) len<<=1;
	a.resize(len); b.resize(len);
	fft(a,false);
	fft(b,false);
	for(int i=0;i<len;i++) a[i]*=b[i];
	fft(a,true);
	return a;
}
}

int p;
struct M{
	int x;
	void operator+=(M o){ x+=o.x; if(x>=p) x-=p; }
	void operator-=(M o){ x-=o.x; if(x<0) x+=p; }
	void operator*=(M o){ x=int(int64_t(x)*o.x%p); }
	friend M operator+(M a,M b){ a+=b; return a; }
	friend M operator-(M a,M b){ a-=b; return a; }
	friend M operator*(M a,M b){ a*=b; return a; }
	M pow(int e)const{
		auto b=*this;
		M re{1};
		while(e){
			if(e&1) re*=b;
			e>>=1;
			b*=b;
		}
		return re;
	}
	M inv()const{
		return pow(p-2);
	}
};

/*
struct C{
	M a,b;
	void operator+(C x){
};
*/
using C=std::complex<M>;

C powC(C b, __int128 e){
	C re{M{1}};
	while(e){
		if(e&1) re*=b;
		e>>=1;
		b*=b;
	}
	return re;
}

int main(){
#if 0
	std::vector<M> a{{1},{2},{3}};
	std::vector<M> b{{4},{5},{6}};
	a=mul(a,b);
	assert(0);
#endif

	std::ios::sync_with_stdio(0);std::cin.tie(0);
	int64_t n;std::cin>>p>>n;
	auto q=(n+1)/p; auto r=int((n+1)%p);

	std::vector<int> p_1_prime_factors;
	{
		int tmp=p-1;
		for(int i=2;tmp!=1;i++) if(tmp%i==0){
			p_1_prime_factors.push_back(i);
			do tmp/=i; while(tmp%i==0);
		}
	}

	M g{2};
	while(std::any_of(begin(p_1_prime_factors),end(p_1_prime_factors),[&](int x){ return g.pow((p-1)/x).x==1; })){
		// then g is not a generator of multiplicative group of Z_p
		g.x+=1;
	}
	assert(g.x<p);


	std::vector<int> lg(p,-1);
	std::vector<M> exp(p-1);
	{
		M g_pow_i{1};
		for(int i=0;i<p-1;i++,g_pow_i*=g){
			lg[g_pow_i.x]=i;
			exp[i]=g_pow_i;
		}
		assert(g_pow_i.x==1);
	}
	lg[0]=0;
	for(auto x:lg) assert(x!=-1);



	auto const solve=[&](int u,int v)->C{
		assert(0<=u and u<=p);
		assert(0<=v and v<=p);
		C re{M{1},M{}};
		if(u==0 or v==0) return re;

		for(int a=1;a<u;a++) re*=C{M{a},M{}};
		for(int b=1;b<v;b++) re*=C{M{},M{b}};
		if(u<=1 or v<=1) return re;

		M tmp{1};
		for(int a=1;a<u;a++) tmp*=M{a};
		tmp=tmp.pow(v-1);

		re*=tmp;

		std::vector<FFT::M> a_pos(p-1), b_pos(p-1);
		for(int a=1;a<u;a++) a_pos[(p-1-lg[a])%(p-1)].x++;
		for(int b=1;b<v;b++) b_pos[lg[b]].x++;
		auto re_pos=FFT::mul(std::move(a_pos),std::move(b_pos));
		while(int(re_pos.size())>p-1){
			re_pos.end()[-p] += re_pos.back();
			re_pos.pop_back();
		}

		for(int i=0;i<int(re_pos.size());i++)
			re*=powC(C{M{1},M{exp[i]}}, re_pos[i].x);

		return re;
	};


	C re{M{1}};
	if(q%p){
		re*=powC(solve(p,p), __int128(q)*q) * powC( solve(p,r) * solve(r,p) , q);
	}
	re*=solve(r,r);
	std::cout<<
		re.real().x
		<<' '<<
		re.imag().x
		<<'\n';
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 0ms
memory: 3312kb

input:

2 1

output:

1 1

result:

ok single line: '1 1'

Test #2:

score: 0
Accepted
time: 3ms
memory: 3384kb

input:

2 2

output:

1 1

result:

ok single line: '1 1'

Test #3:

score: -100
Wrong Answer
time: 4ms
memory: 3256kb

input:

2 3

output:

1 0

result:

wrong answer 1st lines differ - expected: '0 0', found: '1 0'