Particle

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

Codeforces Round #133 (Div. 2)

A.
六角形の個数を求めます。
2<=a,b,c
であるから、a=b=c=2のときを考えて、a,b,cが増えるときどの程度増えるかを考えれば解けます。

int main(){
	int a,b,c,ans=7;
	cin>>a>>b>>c;
	a-=2;b-=2;c-=2;
	ans+=a*3;
	ans+=b*(a+3);
	ans+=c*(a+b+3);
	cout<<ans<<endl;
	return 0;
}

B.
解けない。

C.
貪欲法で解けます。
1日ずつ進めて行って、その日の人数が足りなければ、追加して、次の日に誰もいなければ1人追加しておきます。
この解法で、1日目から、n+m-1日目まで調べれば、n+m日目も鍵を渡せて、それ以降も条件を満たします。

int d[5000],w[5000];

int main(){
	int n,m,k;
	cin>>n>>m>>k;
	int pos = 0;
	while(pos<n+m){
		if(w[pos]<k){
			int t=k-w[pos];
			d[pos]+=t;
			for(int i = 0; i < n; i++){
				w[pos+i]+=t;
			}
		}
		if(w[pos+1]==0){
			d[pos]++;
			for(int i = 0; i < n; i++){
				w[pos+i]+=1;
			}
		}
		pos++;
	}
	int ans=0;
	for(int i = 0; i <=m+n; i++)ans+=d[i];
	cout<<ans<<endl;
	int f=0;
	for(int i = 0; i <=m+n; i++){
		while(d[i]--){
			if(f)cout<<' ';
			cout<<i+1;
			f=1;
		}
	}
	return 0;
}

D.
未読

E.
n進法でabcd([abcd]nとする)があったとき、1桁の数字ができるまで、各桁の和を計算するとき、その1桁の数字は(a+b+c+d)%(n-1)になります(ただし、0になって、a+b+c+d!=0のときはn-1になります)。1が1になることと、n-1になる数字に1を足すと1になる数字になることなどから、分かります。

a_0(=0とする)からa_m(0<=m<=n)までの和(をk-1で割った余り)をすべて計算しておきます。
s_m=a_0+a_1+...+a_mとすると、
a_i+a_(i+1)+...+a_j = s_j - s_(i-1)となるので、a_iからa_jまでの和をO(1)で求められるようになります。

あとは、mapを使って、(s_i+b)%(k-1)=s_j (i

typedef long long ll;

map<int,int> d;
int s[100001];

int main(){
	int k,b,n;
	ll ans0=0,ans=0;
	cin>>k>>b>>n;
	k--;
	ll zero=0;
	++d[0];
	for(int i = 0; i < n; i++){
		int a;
		scanf("%d",&a);
		s[i+1]=(s[i]+a)%k;
		++d[s[i+1]];
		if(a==0)zero++;
		else{
			ans0+=zero*(zero+1)/2;
			zero=0;
		}
	}
	ans0+=zero*(zero+1)/2;
	if(b==0){
		cout<<ans0<<endl;
		return 0;
	}
	if(b%k==0){
		for(int i = 0; i <= n; i++){
			ll t=d[s[i]];
			ans+=t*(t-1)/2;
			d[s[i]]=0;
		}
		cout<<ans-ans0<<endl;
		return 0;
	}
	d.clear();
	for(int i = n; i >= 0; i--){
		int x=(s[i]+b)%k;
		ans+=d[x];
		d[s[i]]++;
	}
	cout<<ans<<endl;
	return 0;
}