2016 CCPC 杭州

A - ArcSoft's Office Rearrangement

均分石子。
好像怎么分答案都一样,于是模拟一遍。

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

template<typename T> inline void read(T &x){
x=0;T f=1;char ch;do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');do x=x*10+ch-'0',ch=getchar();while(ch<='9'&&ch>='0');x*=f;
}

template<typename A,typename B> inline void read(A&x,B&y){read(x);read(y);}
template<typename A,typename B,typename C> inline void read(A&x,B&y,C&z){read(x);read(y);read(z);}
template<typename A,typename B,typename C,typename D> inline void read(A&x,B&y,C&z,D&w){read(x);read(y);read(z);read(w);}

ll a[100005],n,k,x;
ll s;

int main(){
	//freopen("in.txt","r",stdin);
	int T,cas=1;
	cin>>T;
	while(T--){
		read(n,k);
		s=0;
		for(int i=1;i<=n;i++)
			read(a[i]),s+=a[i];
		if(s%k!=0){
			printf("Case #%d: -1
",cas++);
			continue;
		}
		ll cmp = s / k;
		ll ans = 0;
		for(int i=1;i<=n;i++){
			if(a[i]==cmp) continue;
			if(a[i]<cmp){
				if(a[i]+a[i+1]<=cmp){
					a[i+1]=a[i]+a[i+1];
					ans++;
				} else {
					a[i+1]=a[i+1]+a[i]-cmp;
					ans+=2;
				}
			} else {
				ll tmp = a[i] / cmp;
				ll tt  = a[i] % cmp;
				if(tt!=0){
					ans+=2;
					a[i+1]+=tt;
				}
				ans+=tmp-1;
			}
		}
		printf("Case #%d: ",cas++);
		cout<<ans<<endl;
	}
	return 0;
}

B - Bomb

Tarjan之后算一下不同scc里面的cost。

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;


struct infonode {
	ll x,y,r,d;
}info[2005];


struct tarjan {
	const static int maxn = 2e4+7;
	const static int maxm = 2e6+7;
	struct Edge	{
		int to,nxt;
		Edge(){}
		Edge(int _to,int _nxt):to(_to),nxt(_nxt){}
	}edge[maxm];
	int head[maxn],tot,n;
	int Low[maxn],DFN[maxn],Stack[maxn],Belong[maxn];
	int Index,top;
	int scc;
	int num[maxn];
	bool Instack[maxn];
	int Min[maxn];

	inline void init(int n) {
		tot = 0;this->n=n;
		memset(head,-1,sizeof head);
	}

	inline void addedge(int u,int v) {
		edge[tot]=Edge(v,head[u]);
		head[u]=tot++;
	}

	void Tarjan(int u) {
		int v;
		Low[u] = DFN[u] = ++Index;
		Stack[top++] = u;
		Instack[u] = true;
		for(int i=head[u];i!=-1;i=edge[i].nxt){
			v = edge[i].to;
			if(!DFN[v]){
				Tarjan(v);
				Low[u]=min(Low[u],Low[v]);
			} else if(Instack[v] && Low[u]>DFN[v]){
				Low[u]=DFN[v];
			}
		}
		if(Low[u]==DFN[u]){
			scc++;
			do{
				v=Stack[--top];
				Instack[v]=false;
				Belong[v]=scc;
				num[scc]++;
			}while(v!=u);
		}
	}

	int indeg[maxn];

	inline ll solve(int n){
		memset(DFN,0,sizeof DFN);
		memset(num,0,sizeof num);
		memset(Instack,0,sizeof Instack);
		Index = scc = top = 0;
		for(int i=1;i<=n;i++)
			if(!DFN[i]) Tarjan(i);
		memset(indeg,0,sizeof indeg);

		//if(scc==1) return 0;
		for(int u=1;u<=n;u++)
			for(int i=head[u];i!=-1;i=edge[i].nxt){
				int v=edge[i].to;
				if(Belong[u]!=Belong[v]){
					indeg[Belong[v]]++;
				}
			}
		memset(Min,63,sizeof Min);
		for(int i=1;i<=n;i++)
			Min[Belong[i]]=min((ll)Min[Belong[i]],info[i].d);
		ll ret = 0;
		for(int i=1;i<=scc;i++)
			if(indeg[i]==0)
				ret += (ll)Min[i];
		return ret;
	}
} g;

int n,cas=1;

template<typename T> inline void read(T &x){
x=0;T f=1;char ch;do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');do x=x*10+ch-'0',ch=getchar();while(ch<='9'&&ch>='0');x*=f;
}

template<typename A,typename B> inline void read(A&x,B&y){read(x);read(y);}
template<typename A,typename B,typename C> inline void read(A&x,B&y,C&z){read(x);read(y);read(z);}
template<typename A,typename B,typename C,typename D> inline void read(A&x,B&y,C&z,D&w){read(x);read(y);read(z);read(w);}

int main(){
	//freopen("in.txt","r",stdin);
	int T;
	read(T);
	while(T--){
		read(n);
		g.init(n);
		for(int i=1;i<=n;i++)
			read(info[i].x,info[i].y,info[i].r,info[i].d);
		for(int i=1;i<n;i++)
			for(int j=i+1;j<=n;j++){
				ll dist = (ll)(info[i].x-info[j].x)*(info[i].x-info[j].x)+(info[i].y-info[j].y)*(info[i].y-info[j].y);
				if(dist<=info[i].r*info[i].r){
					g.addedge(i,j);
				}
				if(dist<=info[j].r*info[j].r){
					g.addedge(j,i);
				}
			}
		ll ans = g.solve(n);
		printf("Case #%d: ",cas++);
		cout<<ans<<endl;
	}
	return 0;
}

C - Car

模拟分数,否则卡精度,因为涉及多次除被除除。。。

#include <bits/stdc++.h>
#define maxn 100050
using namespace std;
typedef long long LL;
int t,n;
int a[maxn];
int Case=1;
int main(){
	//freopen("in.txt","r",stdin);
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		for(int i=1;i<=n;i++) scanf("%d",&a[i]);
		LL fenzi=a[n]-a[n-1],fenmu=1;
		LL time=1;
		for(int i=n-1;i>=1;i--){
			LL d=a[i]-a[i-1];
			fenmu*=d;
			LL tmp=fenmu/fenzi;
			if(fenmu%fenzi!=0) tmp++;
			time+=tmp;
			fenzi=d;
			fenmu=tmp;
		}
		printf("Case #%d: %lld
",Case++,time);
	}
	return 0;
}

D - Difference

每个k预处理一半,然后用中途相遇法,就是类似尺取。

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

ll a[10][100005],b[10][100005];
ll base[11];
ll P[11][11];

template<typename T> inline void read(T &x){
x=0;T f=1;char ch;do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');do x=x*10+ch-'0',ch=getchar();while(ch<='9'&&ch>='0');x*=f;
}

template<typename A,typename B> inline void read(A&x,B&y){read(x);read(y);}
template<typename A,typename B,typename C> inline void read(A&x,B&y,C&z){read(x);read(y);read(z);}
template<typename A,typename B,typename C,typename D> inline void read(A&x,B&y,C&z,D&w){read(x);read(y);read(z);read(w);}

void init(){
	base[0]=1;
	for(int i=1;i<=10;i++)
		base[i]=base[i-1]*10ll;
	for(int i=0;i<=9;i++){
		P[i][1]=i;
		for(int j=2;j<=9;j++)
			P[i][j]=P[i][j-1]*i;
	}
	for(int kk=1;kk<=9;kk++){
		for(int i=0;i<=99999;i++){
			a[kk][i]=P[i%10][kk]+P[i%100/10][kk]+P[i%1000/100][kk]+P[i%10000/1000][kk]
			+P[i%100000/10000][kk]-(ll)i*100000ll;
			b[kk][i]=P[i%10][kk]+P[i%100/10][kk]+P[i%1000/100][kk]+P[i%10000/1000][kk]
			+P[i%100000/10000][kk]-i;
		}
	}
	for(int i=1;i<=9;i++){
		sort(a[i],a[i]+100000);
		sort(b[i],b[i]+100000);
	}
}

int main(){
	//freopen("in.txt","r",stdin);
	init();
	int T,k,cas=1;
	ll x;
	cin>>T;
	while(T--){
		read(x,k);
		ll res = 0;
		for(int l=0,r=99999;l<=99999 && r;){
			if(a[k][l]+b[k][r]>x)
				r--;
			else if(a[k][l]+b[k][r]<x)
				l++;
			else {
				ll l1=0,r1=0;
				ll t1=a[k][l];
				ll t2=b[k][r];
				while(a[k][l]==t1 && l<=99999) l++,l1++;
				while(b[k][r]==t2 && r!=0) r--,r1++;
				res += l1*r1;
			}
		}
		if(x==0) res--;
		printf("Case #%d: ",cas++);
		cout<<res<<endl;
	}
	return 0;
}

F - Four Operations

贪心+枚举。

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

int cas=1;
char s[55];

int main(){
	//freopen("in.txt","r",stdin);
	int T;
	scanf("%d",&T);
	while(T--){
		scanf("%s",s+1);
		int len=strlen(s+1);
		ll ans = -INT_MAX;
		for(int i=1;i<=len-4;i++){
			for(int j=i+1;j<=len-3;j++){
				ll A=0,B=0,C=0,D=0,E=0;
				for(int c=1;c<=i;c++)
					A=A*10ll+s[c]-'0';
				for(int c=i+1;c<=j;c++)
					B=B*10ll+s[c]-'0';
				C=s[j+1]-'0';
				D=s[j+2]-'0';
				for(int c=j+3;c<=len;c++)
					E=E*10ll+s[c]-'0';
				ll tmp = A + B - C * D / E;
				ans = max(ans,tmp);
			}
		}
		printf("Case #%d: ",cas++);
		cout<<ans<<endl;
	}
	return 0;
}

K - Kingdom of Obsession

二分图匹配,建立匹配边就行。
若有交合部分,s<n
实际上可以由(1...n)-(s+1...s+n)变成(1...s)-(n+1,...,n+s),中间部分自己匹配。

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

const int maxn = 1005;

int matches[maxn];

int link[maxn][maxn];
bool used[maxn];
int n,s;

bool find(int x){
	for(int j=1;j<=n;j++){
		if(link[x][j] && used[j]==false){
			used[j]=1;
			if(matches[j]==0 || find(matches[j])){
				matches[j]=x;
				return 1;
			}
		}
	}
	return 0;
}

int main(){
	//freopen("in.txt","r",stdin);
	int T,cas=1;
	scanf("%d",&T);
	while(T--){
		scanf("%d%d",&n,&s);
		if(s==0){
			printf("Case #%d: Yes
",cas++);
			continue;
		}
		if(n>s) swap(n,s);
		if(n>1000) printf("Case #%d: No
",cas++);
		else {
			memset(link,0,sizeof link);
			memset(matches,0,sizeof matches);
			for(int i=s+1;i<=s+n;i++){
				for(int j=1;j<=n;j++)
					if(i%j==0)
						link[j][i-s]=1;
			}
			int res = 0;
			for(int i=1;i<=n;i++){
				memset(used,0,sizeof used);
				if(find(i)) res++;
			}
			if(res==n){
				printf("Case #%d: Yes
",cas++);
			} else {
				printf("Case #%d: No
",cas++);
			}
		}
	}
	return 0;
}
原文地址:https://www.cnblogs.com/foreignbill/p/7875880.html