KUPC2014

オンラインで参加した。
占いが解けなくてつらい。

A:マッサージチェア
6通りしかないしコピペで全通り書いた

#include <cstdio>
#include <algorithm>
using namespace std;

int a[3];
int b[3];

int d(int x, int y, int z){
	int p = abs(x-a[0]);
	int q = abs(y-a[1]);
	int r = abs(z-a[2]);
	return p + q + r;
}
int main(){
	for(int i=0;i<3;i++)
		scanf("%d", a+i);
	for(int i=0;i<3;i++)
		scanf("%d", b+i);
	int D = 10000000;
	D = min(D, d(b[0],b[1],b[2]));
	D = min(D, d(b[0],b[2],b[1]));
	D = min(D, d(b[1],b[0],b[2]));
	D = min(D, d(b[1],b[2],b[0]));
	D = min(D, d(b[2],b[0],b[1]));
	D = min(D, d(b[2],b[1],b[0]));
	printf("%d\n", D);
}

B:数当てゲーム
Submitデバッグしたら、かなりWAしてしまった。エラトステネスの篩っぽくする。

#include <cstdio>
#include <algorithm>
using namespace std;

bool AI(int x){
	char J[2];
	printf("? %d\n",x);
	fflush(stdout);
	scanf("%s", J);
	if(J[0] == 'Y') return true;
	return false;
}
bool n[1002];
int main(){
	fill(n+1,n+1002,true);
	n[1] = true;
	int z = 2;
	for(int q = 0; q < 200; q++){
		if(!AI(z)){
			for(int j=z; j<1001; j+=z){
				n[j] = false;
			}
		}else{
			for(int i = 1; i < 1001; i++){
				if(i % z != 0){
					n[i] = false;
				}
			} 
			z++;
		}
		for(; ; z++){
			if(n[z]) break;
		}
		if(z > 1000) break;
	}
	for(int i = 1000; i>=1; i--){
		if(n[i]){
			printf("! %d\n", i);
			return 0;
		}
	}
}

C:占い
TLE(絶望)

D:ハミング
二つのバイナリ文字列が一致している箇所の個数A、一致していない箇所の個数Bとして、
d1 = a + b
d2 = a + (B - b)
ただし0<=a<=A, 0<=b<=B
を満たすa,bを求めて、(A C a) * (B C b)の和
繰り返し二乗法を使う必要があるかはよく分からなかったけど、ライブラリがあったので貼り付けた。

#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
const int MOD = 1000000007;
char s[2][100010];
int d[2];
int A, B;
ll mod_pow(ll a, ll n){
	ll ret = 1;
	ll t = a;
	while(n){
		if(n&1)
			ret = ret * t % MOD;
		t = t * t % MOD;
		n >>= 1;
	}
	return ret;
}
//nCk mod p
ll mod_comb(ll N, ll K){
	ll nPk = 1 , kfact = 1;
	ll n = N;
	for(ll i = N; i > N - K; i--)
		nPk = nPk * (i % MOD) % MOD;

	kfact = 1;
	for(ll i = 2; i <= K; i++)
		kfact = kfact * i % MOD;

	kfact = mod_pow(kfact, MOD - 2);
	return ((nPk * kfact) % MOD);
}
int main(){
	for(int i=0;i<2;i++){
		char c;
		scanf("%s",&s[i][0]);
		scanf("%d", &d[i]);
		scanf("%c", &c);
	}
	for(int k = 0; s[0][k] != 0; k++){
		if(s[0][k] == s[1][k]){
			A++;
		}else{
			B++;
		}
	}
	ll ans = 0;
	for(int b=0;b<=B;b++){
		int a = (d[0] - b);
		if(0<=a&&a<=A && d[1] == a+(B-b)){
			ans += (mod_comb(A,a) * mod_comb(B,b)) % MOD;
		}	
	}
	printf("%lld\n", ans);
	return 0;
}

E:何しちゃおっかな
何でこのネーミングなんだろう。
自明に敷き詰められないものを除いて、面積が8で割りきれればよい。

#include <cstdio>
#include <algorithm>
using namespace std;

char p[] = "Possible\n";
char im[] = "Impossible\n";
int main(){
	int N, M, C;
	scanf("%d", &C);
	for(int i = 0; i < C; i++){
		scanf("%d %d", &N, &M);
		if(N==2 && M==4 || N==4&&M==2){
			printf("%s",im);
		}else if(N%4==0&&M%4==0){
			printf("%s",p);
		}else{
			if(N==1 || M==1){
				printf("%s",im);
			}else{
				if((N*M)%8==0)
					printf("%s", p);
				else
					printf("%s", im);
			}
		}
	}
}

J:カード
考える気力がなくなったので部分点だけ取った

#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;

int N, M, P;
int x[100000];
int s[100001];
int main(){
	scanf("%d %d %d", &N, &M, &P);
	for(int i = 0; i < M; i++){
		scanf("%d", x+i);
		s[i+1] = s[i] + x[i];
	}
	int n = 0, w = 0, d = 0;
	for(;;d++){
		w += P;
		int k = distance(s,upper_bound(s,s+M+1,w));
		k--;
		n+=k;
		w-=s[k];
		if(n >= N) break;
	}
	printf("%d\n", d+1);
}

KUPC楽しかったです