Codeforces #400

Codeforces #400

Codeforces 776A A Serial Killer

链接:http://codeforces.com/problemset/problem/776/A

题意:刚开始有两个幸存者,每天会死一个人,新来一个人,输出每天存活人姓名

思路:水题

#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
using namespace std;
int main(){
	string name1,name2;
	string tmp1,tmp2;
	while(cin>>name1>>name2){
		int n;
		cin>>n;
		for(;n!=-1;n--){
			cout<<name1<<" "<<name2<<endl;
			cin>>tmp1>>tmp2;
			if(name1==tmp1) name1=tmp2;
			else name2=tmp2;
		}
	}
	return 0;
}

Codeforces 776B Sherlock and his girlfriend

链接:http://codeforces.com/problemset/problem/776/B

题意:有n个数,2,3,4...n+1,现在需要用尽量少的颜色来将这些数染色,如果一个数能整除另一个数,那么就不能涂同样的颜色

思路:将质数涂1,质数能够整除的数涂2就行了,最多两种颜色,注意一下只有两个数和一个数的情况就行

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
int color[100000+10];
int main(){
	int n;
	while(scanf("%d",&n)!=EOF){
		memset(color,-1,sizeof(color));
		int maxx;
		maxx=2;
		int cnt,cntnow;
		for(int i=2;i<=n+1;i++){
			if(color[i]==-1){
				color[i]=1;
				for(int j=2;j*i<=n+1;j++){
					color[i*j]=2;
				}
			}
		}
		if(n<=2) maxx=1;
		printf("%d\n",maxx);
		for(int i=2;i<=n+1;i++){
			printf("%d ",color[i]);
		}
		printf("\n");
	}
}

Codeforces 776C Molly's Chemicals

链接:http://codeforces.com/contest/776/problem/C

题意:

给一个序列有n个数,问有多少个区间的和是\(K^t\)

思路:

\({sum[j]-sum[i]=k^t =>sum[j]=k^t+sum[i]}\)

因为k的幂次不会很大,所以枚举t,从前往后做,标记\({flag[k^t+sum[i]]}++\),这样做到后面每次有满足这样的前缀和,就说明有\(flag[k^t+sum[i]]\)个区间。枚举的时候注意k=1和-1的时候,可以预处理\(k^t\)

#include <stdio.h>
#include <iostream>
#include <map>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <vector>
using namespace std;
const int MAXN = 1e5+10;
long long a[MAXN];
long long sum[MAXN];
map<long long ,int> m;
vector<long long> Pow;
int n,k;
void init(){
	if(k==1||k==-1) return ;
	Pow.clear();
	long long num=1;
	while(1){
		Pow.push_back(num);
		num*=k;
		if(num>1e15||num<-1e15)break;
	}
}
long long  solve(){
	init();
	memset(sum,0,sizeof(sum));
	sum[0]=0;
	long long cnt=0;
	long long num;
	for(int i=0;i<=n;i++){
		if(i>0)
		sum[i]=sum[i-1]+a[i];
		cnt+=m[sum[i]];
		if(k==1) m[1+sum[i]]++;
		else if(k==-1) m[1+sum[i]]++,m[-1+sum[i]]++;
		else 
		for(int j=0;j<Pow.size();j++){
			num=Pow[j];
			m[num+sum[i]]++;
		}
	}
	return cnt;
}
int main(){
	while(scanf("%d %d",&n,&k)!=EOF){
		m.clear();
		for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
		printf("%lld\n",solve());
	}
	return 0;
}

Codeforces 776D The Door Problem

链接:http://codeforces.com/contest/776/problem/D

题意:n扇门,m个开关,开关可以控制很多扇门,每扇门由一定由两个开关控制,每扇门也有自己初始的状态,问能否按开关使得门都是开的

思路:把开关分成两个点,\(i\)为选择,\(i+m\)为不选择,那么将门作为边,门如果原本是开的,那么要么两个开关都选择,要么两个开关都不选择,如果门本来是关的,那么两个开关只能且一定要选择一个,并查集将两个开关通过门链接起来,最后查询祖先的时候,如果\(fa[i]==fa[i+m]\)说明矛盾,达不到全开的状态

#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;
int n,m;
const int MAXN=2e5+10;
int fa[MAXN];
int door[MAXN];
int Sw[MAXN][2];
void init(){
	for(int i=0;i<2*m+5;i++){
		fa[i]=i;
	}
}
int find(int x){
	return fa[x]=fa[x]==x?x:find(fa[x]);
}
void unite(int x,int y){
	x=find(x),y=find(y);
	fa[x]=y;
}
int main(){
	while(scanf("%d %d",&n,&m)!=EOF){
		init();
		memset(Sw,0,sizeof(Sw));
		for(int i=1;i<=n;i++) scanf("%d",&door[i]);
		for(int i=1;i<=m;i++){
			int cnt;
			int num;
			scanf("%d",&cnt);
			while(cnt--){
				scanf("%d",&num);
				if(!Sw[num][0]) Sw[num][0]=i;
				else Sw[num][1]=i;
			}
		}
		for(int i=1;i<=n;i++){
			if(door[i]){
				unite(Sw[i][0],Sw[i][1]);
				unite(Sw[i][0]+m,Sw[i][1]+m);
			}
			else {
				unite(Sw[i][0],Sw[i][1]+m);
				unite(Sw[i][0]+m,Sw[i][1]);
			}
		}
		bool flag=true;
		for(int i=1;i<=m;i++){
			if(find(i)==find(i+m)){
				flag=false;
				break;
			}
		}
		if(flag){
			puts("YES");
		}
		else puts("NO");
	}	
}

Codeforces 776E The Holmes Children

链接:http://codeforces.com/contest/776/problem/E

题意:\(f(n)\)表示\(f(1)=1\),\(n≥2\)时有多少个\((x,y)\)满足\(x+y=n \quad and \quad gcd(x,y)=1\)\(g(n)=\sum_{d|n}f(n/d)\),\(F_{k}(n)=\begin{cases}f(g(n),&\text{for k =1}\\ g(F_{k-1}(n)),&\text{for k > 1 and k mod 2 = 0}\\ f(F_{k-1}(n)),&\text{for k > 1 and k mod 2 = 1} \end{cases}\)

\(F_{k}(n)\text{ mod 1e9+7}\)

思路:\(f(n)\)表示\(f(1)=1\),\(n≥2\)时有多少个\((x,y)\)满足\(x+y=n\) \(and\) \(gcd(x,y)=1\)

\(gcd(x,n-x)=1=>gcd(x,n)=1\) 即有多少个小于n的数与x互质,即欧拉函数的定义,\(f(x)=phi(x)\) ,\(g(n)=\sum_{i=1}^{n}f(d)[d|n]\),即莫比乌斯反演公式,\(g(n)=n\),也就是求(k+1)/2次\(𝛷(𝛷(𝛷(...)))\)

现在证明 \(g(n)=\sum_{i=1}^{n}f(d)[d|n]=n\)

\(g(n)={\sum}_{d|n}𝛷(d),n=\prod^{k}_{i=1}p^{e_i}_{i}\),\(p\)\(n\)的质因数。

根据莫比乌斯反演的充分必要性,\(𝛷(n)\)为积性函数,则\(g(n)\)也为积性函数

\(g(n)=\prod^{k}_{i=1}g(p_i^{e_i})\)\(g(p^k)=\sum_{i=0}^kf(p^i)\) 因为\(f(x)=𝛷(x)\)

所以\(g(p^k)=\sum_{i=0}^kf(p^i)\)=\(\sum_{i=0}^k𝛷(p^i)\)

因为$ 𝛷(pi)=pi(1-\frac{1}{p})=pi-p,\quad i\geq1$

所以\(\sum^k_{i=0}𝛷(p^i)\)=1+\(\sum^k_{i=1}𝛷(p^i)\)=1+\(p^k\)-1=\(p^k\)

所以\(g(p^k)=p^k\),即\(g(n)=n\)

#include <stdio.h>
const int mod=1e9+7;
long long res,a;
long long phi(long long n){
 	res=n,a=n;  
     for(long long  i=2;i*i<=a;i++){  
         if(a%i==0){  
             res=res/i*(i-1); 
             while(a%i==0) a/=i;  
         }  
     }  
     if(a>1) res=res/a*(a-1);  
     return res;  
}
int main(){
	long long n,k;
	while(scanf("%lld %lld",&n,&k)!=EOF){
		long long ans=n;
		k=(k+1)/2;
		while(k--){
			if(ans==1){
				break;
			}
			ans=phi(ans);
		}
		printf("%lld\n",ans%mod);
	}
	return 0;
}
posted @ 2017-02-27 16:22  as3asddd  阅读(209)  评论(0编辑  收藏  举报