Particle

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

ABBYY Cup 2.0 - Easy

4時間のコンテストでした。
A.
n×nの行列の対角と中央の行と列にある数字をすべて足します。
普通に足して、中央の数字の3倍を引いても良いです。

int g[128][128];

int main(){
	int n,ans = 0;
	cin>>n;
	for(int i = 0; i < n; i++){
		for(int j = 0; j < n; j++){
			cin>>g[i][j];
		}
	}
	
	//main diagonal
	for(int i = 0; i < n; i++){
		ans += g[i][i];
		g[i][i] = 0;
	}
	
	//secondary diagonal
	for(int i = 0; i < n; i++){
		ans += g[i][n-i-1];
		g[i][n-i-1] = 0;
	}
	
	//middle row
	for(int i = 0; i < n; i++){
		ans += g[n/2][i];
		g[n/2][i] = 0;
	}
	
	//middle column
	for(int i = 0; i < n; i++){
		ans += g[i][n/2];
		g[i][n/2] = 0;
	}
	
	cout<<ans<<endl;
	
	return 0;
}

B.
小さい方から素因数分解します。
√n以下の素数でnを割ると、√nより大きい素因数だけが残るので、O(√n)で計算できます。

typedef long long ll;


int main(){
	int n,n2;
	ll ans = 0;
	cin>>n;
	n2 = n;
	while(!(n&1)){
		ans += n;
		n >>= 1;
	}
	
	for(int i = 3; i*i <= n2; i+=2){
		while(!(n%i)){
			ans += n;
			n /= i;
		}
	}
	if(n-1){
		ans += n;
	}
	
	cout<<ans+1<<endl;
	return 0;
}

C.
Union-Find木を書くだけです。

struct UF {
	int par[2000],rank[2000];
	
	void init(int n){
		for(int i = 0; i < n; i++){
			par[i] = i;
			rank[i] = 0;
		}
	}
	
	int find(int x){
		if(par[x] == x){
			return x;
		}else{
			return par[x] = find(par[x]);
		}
	}
	
	void unite(int x, int y){
		x = find(x);
		y = find(y);
		if(x == y) return;
		
		if(rank[x] < rank[y]){
			par[x] = y;
		}else{
			par[y] = par[x];
			if(rank[x] == rank[y]) rank[y]++;
		}
	}
	
	bool same(int x, int y){
		return find(x) == find(y);
	}
};

int friends[2000];

int main(){
	UF uf;
	int n,k,m;
	scanf("%d%d",&n,&k);
	uf.init(n);
	for(int i = 0; i < k; i++){
		int a,b;
		scanf("%d%d",&a,&b);
		uf.unite(a-1,b-1);
	}
	scanf("%d",&m);
	for(int i = 0; i < m; i++){
		int a,b;
		scanf("%d%d",&a,&b);
		if(uf.same(a-1,b-1)){
			friends[uf.find(a-1)] = -1e9;
		}
	}
	
	for(int i = 0; i < n; i++){
		friends[uf.find(i)]++;
	}
	sort(friends,friends+n);
	printf("%d\n",friends[n-1]);
	
	return 0;
}

D.
部分和を求める問題。数列b_iの負の項を0と考えることで、実装が楽になります。
100000増やしておきましたが、mapを使っても良さそうです。

int a[100000],b[200000];
int n,m,mod;

int main(){
	scanf("%d%d%d",&n,&m,&mod);
	for(int i = 0; i < n; i++) scanf("%d",a+i);
	for(int i = 0; i < m; i++) scanf("%d",b+i+100000);
	
	int sum = 0,en = n-m+1;
	
	for(int i = 0; i < n; i++){
		sum -= b[i+100000-en];
		sum += b[i+100000];
		if(sum<0) sum += mod;
		sum %= mod;
		a[i] = (a[i]+sum) % mod;
	}
	printf("%d",a[0]);
	for(int i = 1; i < n; i++) printf(" %d",a[i]);
	printf("\n");
	return 0;
}


E.読めない
F.解けない
G.解けない