Particle

競技プログラミングについての雑記

Codeforces Round #138 (Div. 2)

A

最初O(n^3)で書いてhackされてしまった。(O(n^3)のままですが、適当にbreakとかcontinueしてるので問題ないです)

ソース

int main(){
	int a[3];
	cin>>a[0]>>a[1]>>a[2];
	sort(a,a+3);
	for(int i = 1; i <= 10000; i++){
		if(a[0]%i||a[1]%i)continue;
		for(int j = i; j <= 10000; j++){
			if(j>a[0])break;
			if(a[0]!=i*j||a[2]%j)continue;
			for(int k = j; k <= 10000; k++){
				if(k>a[1])break;
				if(j*k==a[2]&&k*i==a[1]){
					cout<<4*(i+j+k)<<endl;
					return 0;
				}
			}
		}
	}
	return 0;
}

B

条件を満たすl,rを一つ出力すればいいらしい。最初少しバグがでて時間がかかった。

解法

適当にバグらないように尺取りする。

ソース

int a[100000],d[100001];

int main(){
	int n,k;
	cin>>n>>k;
	for(int i = 0; i < n; i++)cin>>a[i];
	int l = -1, r = -1;
	int x = 0,y = -1,s = 0;
	while(x<n){
		if(s<k&&y<n-1){
			y++;
			if(!d[a[y]])s++;
			d[a[y]]++;
		}else {
			d[a[x]]--;
			if(!d[a[x]])s--;
			x++;
		}
		if(s==k && (r==-1 || r-l>y-x)){
			l = x+1,r = y+1;
		}
		//cout<<s<<' '<<x<<' '<<y<<endl;
	}
	
	cout<<l<<' '<<r<<endl;
	return 0;
}

E

数列の和をk(<=10^9)回計算する。少しバグがでてsubmit間に合わなかった。
色々考察すると面白そうな問題だった。

解法

累積和を拡張すると、累乗の計算みたいな感じになるので、繰り返し二乗法で解ける(O(n^2 * log k)で遅いけど)。
array[] = {a,b,c,d,e}
f(n,array) = arrayに問題文の操作をn回行ったもの
とすると、
f(0,array) = {a,b,c,d,e}
f(1,array) = {a,a+b,a+b+c,a+b+c+d,a+b+c+d+e}
f(2,array) = {a,2a+b,3a+2b+c,4a+3b+2c+d,5a+4b+3c+2d+e}
f(3,array) = {a,3a+b,6a+3b+c,10a+6b+3c+d,15a+10b+6c+3d+e}
f(4,array) = {a,4a+b,10a+4b+c,20a+10b+4c+d,35a+20b+10c+4d+e}
...

無証明ですが、f(n+m,array) = f(n,f(m,array)) が成り立ちます。

全部計算する必要は無いので、必要なところだけ計算すれば良いです。(計算の仕方はソース内のmal()を見てください)
どうみても累乗の計算なので、配列の要素の個数をnとすると最初に書いたオーダーでf(k,array)を計算できます。

ソース

typedef long long ll;

ll a[2000],r[2000],t[2000];
int n;
const int mod = 1000000007;

void mal(ll* x, ll* y){
	memset(t,0,sizeof(t));
	for(int i = 0; i < n; i++){
		for(int j = 0; j <= i; j++){
			t[i] = (t[i]+x[j]*y[i-j])%mod;
		}
	}
	for(int i = 0; i < n; i++){
		x[i] = t[i];
	}
}

int main(){
	int k;
	cin>>n>>k;
	for(int i = 0; i < n; i++)cin>>a[i];
	for(int i = 0; i < n; i++)r[i]++;
	
	for(;k;k>>=1){
		if(k&1)mal(a,r);
		mal(r,r);
	}
	cout<<a[0];
	for(int i = 1; i < n; i++){
		cout<<' '<<a[i];
	}
	cout<<endl;
	return 0;
}