CF225 Round #139 题解

比赛链接:https://codeforces.com/contest/225

题解:
A
题意题

// by SkyRainWind
#include <bits/stdc++.h>
#define mpr make_pair
#define debug() cerr<<"Yoshino\n"
#define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define pii pair<int,int>

using namespace std;

typedef long long ll;
typedef long long LL;

const int inf = 1e9, INF = 0x3f3f3f3f;

signed main(){
	int n,m;scanf("%d%d",&n,&m);
	while(n--){
		int x,y;cin>>x>>y;
		if(x+y==7||x==y||x==m||y==m||x==7-m||y==7-m)return puts("NO"),0;
	}
	puts("YES");

	return 0;
}

B
斐波那契数列增长的挺快,因此暴力求就可以

// by SkyRainWind
#include <bits/stdc++.h>
#define mpr make_pair
#define debug() cerr<<"Yoshino\n"
#define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define pii pair<int,int>
 
using namespace std;
 
typedef long long ll;
typedef long long LL;
 
const int inf = 1e9, INF = 0x3f3f3f3f;
 
int k,n;
map<int,ll>fib;
int s;
signed main(){
	scanf("%d%d",&s,&k);
	fib[k] = 1;
	ll sum = 1,t;
	for(int i=k+1;i<=k+100;i++){
		fib[i] = sum;
		sum = sum + fib[i] - (i-k < k ? 0 : fib[i-k]);
//		printf("%d %d\n",i,sum);
		if(sum > s){t=i;break;}
	}
//	for(auto it : fib)printf("%d %d\n",it.first,it.second);
	vector<int>vc;
	for(int i=t;i>=k;i--)
		if(s >= fib[i])s -= fib[i], vc.push_back(fib[i]);
	vc.push_back(0);
	printf("%d\n",vc.size());
	for(auto it : vc)printf("%d ",it);
 
	return 0;
}

C
线性dp,设 \(dp[i][0/1]\) 表示当前是第 \(i\) 位,当前位置是./#,且与上一个位置不同的最少步数
显然转移从 \(i=x+1\) 开始。
细节略多,注意 \(x,y\) 不一定 \(\leq m\)

// by SkyRainWind
#include <bits/stdc++.h>
#define mpr make_pair
#define debug() cerr<<"Yoshino\n"
#define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define pii pair<int,int>

using namespace std;

typedef long long ll;
typedef long long LL;

const int inf = 1e9, INF = 0x3f3f3f3f;

int n,m,x,y;
char s[1005][1005];
int col[1005],ncol[1005];
int dp[1005][2];
// dp[i][0/1] 到第 i 位,且 (i-1,i) 不同 第 i 位为 ./# 

signed main(){
	memset(dp, 0x3f, sizeof dp);
	scanf("%d%d%d%d",&n,&m,&x,&y);
	y =min(y, m);x = min(x, m);
	for(int i=1;i<=n;i++)
		scanf("%s",s[i] + 1);
	for(int j=1;j<=m;j++){
		int r=0;
		for(int i=1;i<=n;i++)
			if(s[i][j] == '.')++r;
		col[j] = r;
		ncol[j] = n-r;
	}
	for(int j=2;j<=m;j++)col[j] += col[j-1], ncol[j] += ncol[j-1];
	int ans = 1e9;
	for(int i=x+1;i<=y+1;i++){
		// []
		dp[i][0] = col[i-1], dp[i][1] = ncol[i-1];
	}
	if(y == m)ans = min(ans, min(col[m], ncol[m]));
	for(int i=x+2;i<=m;i++){
		for(int j=i-y;j<=i-x;j++)if(j >= 1){
			if(dp[j][1]!=INF)dp[i][0] = min(dp[i][0], dp[j][1] + col[i-1] - col[j-1]);
			if(dp[j][0]!=INF)dp[i][1] = min(dp[i][1], dp[j][0] + ncol[i-1] - ncol[j-1]);
		}
	}
	for(int j=m+1-y;j<=m+1-x;j++)if(j>=1)
		ans = min(ans, dp[j][0] + ncol[m] - ncol[j-1]),
		ans = min(ans, dp[j][1] + col[m] - col[j-1]);
	cout<<ans;

	return 0;
}

D
考虑蛇的一次移动如何表示,例如:

34.
21.

考虑先把蛇的每一个位置都+1,然后去掉最末尾的一个。这一步相当于身体的移动

4..
32.

再考虑头该如何移动:

41. 4..
32. 321

两种都是可以的
(注意这样还能省去判断头和尾刚好差一格也是能移动的情况)
然后就是普通的bfs,但是还需要判断当前位置是否访问过,有两种情况:

  • 对整个地图 hash。自然溢出可能会被卡,普通hash可能常数过大(最大点需要4.4s,TLE)
  • 对蛇 hash(就是记一下 1~9 的位置然后hash),最大点只需要 ~2s
// by SkyRainWind
#include <bits/stdc++.h>
#define mpr make_pair
#define debug() cerr<<"Yoshino\n"
#define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define pii pair<int,int>

using namespace std;

typedef long long ll;
typedef long long LL;
typedef unsigned long long ull;

const int inf = 1e9, INF = 0x3f3f3f3f, maxn = 17;
const int p = 998244353, p2 = 990804011;

int n,m;
char s[maxn][maxn];
struct state{
	char st[maxn][maxn];
	int cnt;
	
	ull gethash(){
		ull hs = 0;
		ull hs2 = 0;
		for(int i=1;i<=n;i++)
			for(int j=1;j<=m;j++)
				hs = hs*p + st[i][j],
				hs2 = (hs2*p2 + st[i][j]);
		return hs*127+hs2;
	}
	
	state(){cnt=0;}
}hajime;

int dx[] = {-1,0,1,0};
int dy[] = {0,1,0,-1};
unordered_map<ull,int>vis;
queue<state>Q;
int ans = -1, len = 0;

int ind(int x,int y){return (x-1)*n+y;}
int in(int x,int y){return x>=1 && x<=n && y>=1 && y<=m;} 
ull hsh(int *pp){
	ull now=0;
	for(int i=1;i<=len;i++)now=now*p+pp[i];
	return now;
}

void move(state now){
	int tmp[12];
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			if(now.st[i][j] >= '1' && now.st[i][j] <= '9'){
				now.st[i][j] ++;
				if(now.st[i][j] < len + '1')tmp[now.st[i][j] - '0'] = ind(i, j);
			}
	int bx, by;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++){
			if(now.st[i][j] == '2')
				bx = i, by = j;
			if(now.st[i][j] == len + '1')
				now.st[i][j] = '.';
		}
	
	now.cnt ++;
	for(int i=0;i<4;i++){
		int fx = bx + dx[i], fy = by + dy[i];
		if(!in(fx, fy))continue;
		if(now.st[fx][fy] == '@'){
			ans = now.cnt;
			return ;
		}else if(now.st[fx][fy] == '.'){
			tmp[1] = ind(fx, fy);
			now.st[fx][fy] = '1';
			ull nowhs = hsh(tmp);
			if(!vis.count(nowhs)){
				vis[nowhs] = 1;
//				vis.insert(nowhs);
				Q.push(now);
			}
			now.st[fx][fy] = '.';
		}
	}
}

signed main(){
	scanf("%d%d",&n,&m);
	
	for(int i=1;i<=n;i++)scanf("%s",hajime.st[i] + 1);
	
	int tmp[12];
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			if(hajime.st[i][j] >= '1' && hajime.st[i][j] <= '9')
				len = max(len, hajime.st[i][j] - '0'),
				tmp[hajime.st[i][j] - '0'] = ind(i, j);
	hajime.cnt = 0;
	vis[hsh(tmp)] = 1;
//	vis.insert(hajime.gethash());
	Q.push(hajime);
	
	while(!Q.empty()){
		state now = Q.front(); Q.pop();
		
		move(now);
		if(~ans)break;
	}
	cout<<ans;

	return 0;
}

E
\(x=2k+1\)
\(z = k + 2y + 2ky\)
\(z+1 = (k+1)(2y+1)\)
注意如果 z+1 含有 >1 的奇数因子的话一定能被表示出来,所以不能含有,即 \(z = 2^r-1\)

\(x=2k\)
\(z = k + y + 2ky\)
\(2z+1 = (2k+1)(2y+1)\)
因此 \(2z+1\) 必然是奇素数,而 \(z = 2^r-1\)
代入有 \(2^{r+1}-1\) 是素数,这就是梅森素数
从oeis上拖一个1~40的梅森素数(注意oeis上对应的项就是 r+1),然后代入原式求出 \(z\) 即可。

// LUOGU_RID: 100275489
// by SkyRainWind
#include <bits/stdc++.h>
#define mpr make_pair
#define debug() cerr<<"Yoshino\n"
#define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define pii pair<int,int>

using namespace std;

typedef long long ll;
typedef long long LL;

const int inf = 1e9, INF = 0x3f3f3f3f,mod=1e9+7;

int pm[] = {0, 2, 3, 5, 7, 13, 17, 19, 31, 61, 89, 107, 127, 521, 607, 1279, 2203, 2281, 3217, 4253, 4423, 9689, 9941, 11213, 19937, 21701, 23209, 44497, 86243, 110503, 132049, 216091, 756839, 859433, 1257787, 1398269, 2976221, 3021377, 6972593, 13466917, 20996011}; 
int pw(int x,int y){
	if(!y)return 1;
	if(y==1)return x;
	int mid=pw(x,y>>1);
	if(y&1)return 1ll*mid*mid%mod*x%mod;
	return 1ll*mid*mid%mod;
}
signed main(){
	int n;scanf("%d",&n);
	printf("%d\n",pw(2, pm[n]-1)-1);
	
	return 0;
}
posted @ 2023-01-20 10:24  SkyRainWind  阅读(22)  评论(0编辑  收藏  举报