【题解】cf1551

CF1551D1 Domino (easy version)

考点:数学+分类讨论。

先考虑竖着的情况。显然每次选择两个相邻的列使得行数减少 1 。最后每一列的行数都必须是偶数。分奇偶讨论即可。

#include<bits/stdc++.h>
#define ll long long
#define PII pair<int,int>
#define All(a) a.begin(),a.end()
using namespace std;
int cnt[105];
int main() {
	int T; cin>>T;
	while(T--) {
		int n,m,k,ok=0; cin>>n>>m>>k; for(int i=1;i<=m;i++) cnt[i]=n;
		if(n%2==0) printf("%s\n",(k%2==0&&n*(m/2)>=k)?"yes":"no");
		else printf("%s\n",(m%2==0&&(k-m/2)%2==0&&k>=m/2)?"yes":"no");
	}
} 

CF1551D2 Domino (hard version)

考点:模拟

根据四色定理可知,方案一定有解。

#include<bits/stdc++.h>
#define ll long long
#define PII pair<int,int>
#define All(a) a.begin(),a.end()
using namespace std;
int cnt[105],n,m,k;
int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
char ans[105][105];
bool ch[26];
void paint(int x,int y,int x2,int y2) {
	memset(ch,0,sizeof(ch));
	for(int i=0;i<4;i++) {
		int tx=x+dx[i],ty=y+dy[i];
		if(ans[tx][ty]) ch[ans[tx][ty]-'a']=1;
	}
	for(int i=0;i<4;i++) {
		int tx=x2+dx[i],ty=y2+dy[i];
		if(ans[tx][ty]) ch[ans[tx][ty]-'a']=1;
	}
	for(int i=0;i<26;i++) 
	    if(!ch[i]) {
	    	ans[x][y]=ans[x2][y2]='a'+i;
	    	return;
		}
}
void output() {
	for(int i=1;i<=n;i++) {
		for(int j=1;j<=m;j++) {
			printf("%c",ans[i][j]);
		}
		printf("\n"); 
	}
} 
int main() {
	int T; cin>>T;
	while(T--) {
		int ok=0; cin>>n>>m>>k; for(int i=1;i<=m;i++) cnt[i]=n;
		memset(ans,0,sizeof(ans));
		if(n%2==0) {
			if(k%2==0&&n*(m/2)>=k) {
				printf("YES\n");
				for(int i=1;i<n;i+=2) {
					for(int j=1;j<m;j+=2) {
						if(k) {
							paint(i,j,i,j+1);
							paint(i+1,j,i+1,j+1);
							k-=2; 
						}
					}
				}
				for(int i=1;i<=n;i++) {
					for(int j=1;j<=m;j++) {
						if(!ans[i][j]) {
							paint(i,j,i+1,j);
						}
					}
				}
				output();
			}
			else {
				printf("NO\n");
			}
		}
		else {
		    if(m%2==0&&k>=m/2&&(k-m/2)%2==0) {
		    	printf("YES\n");
		    	for(int i=1;i<m;i+=2) {
		    		paint(1,i,1,i+1);
		    		k--;
				}
				for(int i=2;i<n;i+=2) {
					for(int j=1;j<m;j+=2) {
						if(k) {
							paint(i,j,i,j+1);
							paint(i+1,j,i+1,j+1);
							k-=2;
						}
					}
				}
				for(int i=1;i<=n;i++) {
					for(int j=1;j<=m;j++) {
						if(!ans[i][j]) {
							paint(i,j,i+1,j);
						}
					}
				}
		    	output();
			}
			else {
				printf("NO\n");
			}
		}
	}
} 

CF1551E Fixed Points

考点:dp状态。 设 dp[i][j] 表示前 i 个数,i 的排名为 j 的最大匹配数,那么答案显然可以算。

转移方程为:dp[i][j] = max(dp[i-1][j], dp[i-1][j-1] + (j == a[i]))

CF1551F Equidistant Vertices

直接 n^3 暴力计算即可。

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define ll long long
#define PII pair<int,int>
#define All(a) a.begin(),a.end()
using namespace std;
const int mx=1e9+7;
const int mod=1e9+7;
int n,k,dep[105];
ll res,c[105][105],f[105][105],dp[105][105]; 
vector<int> g[105];
//k>=4 时比较复杂
//换根dp + 组合数学 
void dfs(int x,int fa) {
	f[x][0]=1;
	for(auto y:g[x]) {
		if(y==fa) continue;
		dfs(y,x);
		for(int i=1;i<=n;i++) {
			f[x][i]+=f[y][i-1]; 
		}
	}
}
int main() {
	for(int i=0;i<=100;i++) c[i][0]=1;
	for(int i=1;i<=100;i++) {
		for(int j=1;j<=100;j++) {
			c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod; 
		}
	} 
	int T; scanf("%d",&T);
	while(T--) {
		memset(f,0,sizeof(f)); res=0;
		scanf("%d%d",&n,&k);
		for(int i=1;i<=n;i++) g[i].clear();
		for(int i=1;i<n;i++) {
			int x,y; scanf("%d%d",&x,&y);
			g[x].push_back(y),g[y].push_back(x);
		}
		if(k==2) {
			printf("%d\n",n*(n-1)/2);
			continue;
		}
		for(int u=1;u<=n;u++) {
			for(int i=1;i<=n;i++) {
				for(int j=0;j<=n;j++) {
					f[i][j]=0;
				}
			}
			dfs(u,0);
			for(int i=1;i<=n;i++) {
				for(int j=1;j<=k;j++) dp[i][j]=0;
				dp[i][0]=1; 
			}
			for(auto v:g[u]) {
				for(int i=1;i<=n;i++) {
					for(int j=k;j>=1;j--) {
						dp[i][j]=(dp[i][j]+dp[i][j-1]*f[v][i-1]%mod)%mod;
					}
				}
			}
			for(int i=1;i<=n;i++) res=(res+dp[i][k])%mod;
		}
		printf("%lld\n",res);
	}
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值