2020年10月26日普及组

A魔法部落
B圆盘题解
C棋盘行走
D走方格题解

A

在这里插入图片描述
本题使用等比数列求和公式即可得到以下答案
a n s = ( 3 n − 1 ) 2 ans=\frac{(3^n-1)}{2} ans=2(3n1)
之后逆元即可在log的复杂度内解决本题。
一个数在摸 P P P意义下的逆元怎么求:
b^(p-2)%p

#include<iostream>
#include<cstdio>
using namespace std;
long long n;
int main()
{
	scanf("%lld", &n);
	long long x=3;
	long long sum=1;
    while(n!=0){
        if(n&1)
	   		sum=sum*x%1000000007;
        x=x*x%1000000007;
        n>>=1;
	}
	sum=3*(1-sum)*1000000008/(-2)%1000000007;
	printf("%lld", (sum+1)%1000000007);
	return 0;
} 

B

在这里插入图片描述
这里用最小表示法来做。可以在 O ( n 2 ) O(n^2) O(n2)求出所有最小表示,然后可以 O ( n ) O(n) O(n)统计有多少对相同。
最小表示模板

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
int n, m, p;
int a[510][1010], b[10010];
int MRA[10010];
int mra(int t[])
{
	int i=1, j=2, k;
	while(i<=2*m&&j<=2*m)
	{
		for(k=0; k<=2*m&&t[i+k]==t[j+k]; k++);
		if(k==m*2)
			break;
		if(t[i+k]<t[j+k])
		{
			i+=k+1;
			if(i==j)
				i++;
		}
		else
		{
			j+=k+1;
			if(i==j)
				j++;
		}
	}
	return min(i, j);
}
int main()
{
	scanf("%d%d%d", &n, &m, &p);
	for(register int i=1; i<=n; ++i)
	{
		
		for(register int j=1; j<=m; ++j)
			scanf("%d", &b[j]);
		sort(b+1, b+1+m);
		for(int j=1; j<m; j++)
		{
			a[i][j]=abs(b[j+1]-b[j]);
			a[i][j+m]=a[i][j];
		}
		a[i][m]=a[i][2*m]=b[1]+p-b[m];
		MRA[i]=mra(a[i]);
	}
	register int sum=0;
	for(register int i=1; i<=n; ++i)
		for(register int j=i+1; j<=n; ++j)
		{
			int q1, p1, flag=1;
			q1=MRA[i];
			p1=MRA[j];
			for(int k=1; k<=m; k++)
				if(a[i][q1+k-1]!=a[j][p1+k-1])
				{
					flag=0;
					break;
				}
			if(flag)
				sum++;
		}
	printf("%d", sum);
	return 0;
}
 

C

在这里插入图片描述
数据水的一批,爆搜直接AC

#include<iostream>
#include<cstdio>
using namespace std;
int n, m, flag=0;
char a[2501][2501];
bool f[2501][2501], f1[2501][2501];
int dx[4]={0, 1, 0, -1};
int dy[4]={1, 0, -1, 0};
void dfs(int x1, int y1, int x, int y, int d)
{
	if(flag)
		return;
	if(x1==x&&y1==y&&d>=4)
	{
		printf("Yes");
		flag=1;
		return;
	}
	for(int i=0; i<4; i++)
	{
		int xx=x+dx[i];
		int yy=y+dy[i];
		if(a[xx][yy]!=a[x][y]||xx<1||xx>n||yy<1||yy>m||f1[xx][yy]==1)
			continue;
		f1[xx][yy]=1;
		dfs(x1, y1, xx, yy, d+1);
		f1[xx][yy]=0;
	}
} 
int main()
{
	cin>>n>>m;
	for(int i=1; i<=n; i++)
		for(int j=1; j<=m; j++)
			scanf("%1s", &a[i][j]);
	for(int i=1; i<=n; i++)
		for(int j=1; j<=m; j++)
			{
				dfs(i, j, i, j, 0);
				if(flag)
					return 0;
			}
	printf("No");
	return 0;
}

D

在这里插入图片描述
首先分别预处理奇数位偶数位的前缀和和后缀和。
如果去掉第i个数,那么前i个数不变,后面的数下标奇偶性取反
之后 O ( n ) O(n) O(n)枚举位置并检查即可。

#include<iostream>
#include<cstdio>
using namespace std;
int n, a[1001000], b[1001000], a1, b1;
int t[1001000];
int main()
{
	scanf("%d", &n);
	for(int i=1; i<=n; i++)
	{
		scanf("%d", &t[i]);
		if(i%2==0)
			b[i]=b[i-1]+t[i],
			a[i]=a[i-1];
		else
			b[i]=b[i-1],
			a[i]=a[i-1]+t[i];
	}
	int sum=0;
	for(int i=1; i<=n; i++)
	{
		int as, bs;
		as=a[i-1]+b[n]-b[i],
		bs=b[i-1]+a[n]-a[i];
		if(as==bs)
			sum++;
	}
	printf("%d", sum);
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值