kmjp's blog

競技プログラミング参加記です

yukicoder : No.1409 Simple Math in yukicoder

数学問はしんどいな…。
https://yukicoder.me/problems/no/1409

問題

整数v,xが与えられる。vx+1は素数である。
1~xvの範囲で相異なるx要素の整数列Aのうち、下記を満たすものを求めよ。

  •  \sum_i {A_i}^kは、kがx未満の時xv+1で割り切れ、kがxの時xv+1で割ると1余る。

解法

詳細はEditorialに譲るとして、p=vx+1とし、原始根qに対しq^v,q^2v,q^3v....,q^xvという数列を考えると、この数列は条件を満たす。
原始根qは、1~(p-1)の中にφ(p-1)個と結構あるので、適当に乱択すると見つかる。

ll modpow(ll a, ll n,ll mo) {
	ll r=1;a%=mo;
	while(n) r=r*((n%2)?a:1)%mo,a=a*a%mo,n>>=1;
	return r;
}

int T;
int V,X;

void solve() {
	int i,j,k,l,r,x,y; string s;
	
	cin>>T;
	while(T--) {
		cin>>V>>X;
		int P=V*X+1;
		
		if(P==2) {
			cout<<1<<endl;
			continue;
		}
		vector<int> cand;
		for(i=2;i*i<=P-1;i++) if((P-1)%i==0) {
			cand.push_back(i);
			cand.push_back((P-1)/i);
		}
		
		
		int q=0;
		set<int> S;
		while(1) {
			q=rand()%(P-1)+1;
			int ok=1;
			FORR(c,cand) if(modpow(q,c,P)==1) ok=0;
			if(ok==0) continue;
			FOR(i,X) S.insert(modpow(q,V*(i+1),P));
			break;
		}
		
		FORR(v,S) cout<<v<<" ";
		cout<<endl;
	}
}

まとめ

yukicoderってAtCoderより数学問多い気がする。
Project Eulerとかやるとここらへん強くなるのかな?