前言
今晚讲的是暴力枚举
相信大家都听懂了吧
暴力枚举只是一种思想,具体的问题还需要具体分析。
觉得自己掌握不太熟练的同学可以去洛谷上再多刷一些相关的题型
暴力枚举
下面开始今晚比赛的题解:
比赛题解
A 统计方形
首先,统计一个n*m的矩形里有多少个正方形,长方形。
要明确,正方形和长方形都是矩形,那么n*m的矩形里的
矩形数=正方形数+长方形数
明确这一点后,就可以一次求出二者了
如图,长为2宽为1的小长方形用〇来表示,那么
横向排列的就有 *(n-1)m 个
竖向排列的就有 n(m-1)* 个
证明:
∵ 矩形长不等于宽 ∴ 子矩形构成的矩阵的长宽是由原矩形长宽减去不同数而得 即(n-b)*(m-a) (a≠b)
#include<stdio.h>
long long n,m,rec,sqr;
int main() {
scanf("%lld %lld", &n,&m);
for(int i=0; i<n; i++)//循环,从n-0到n-(n-1)
for(int j=0; j<m; j++) {//循环,从m-0到m-(m-1)
if(i==j) sqr+=(n-i)*(m-j);//如果i==j,说明是正方形
else rec+=(n-i)*(m-j);//如果不等说明是矩形
}
cout<<sqr<<" "<<rec<<endl;//输出
printf("%lld %lld",sqr,rec);
return 0;
}
B 分数拆分
暴力跑就完事了
#include<stdio.h>
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
/*//已知K,用一个变量表示Y,则另一个数X可以用含Y和K的式子表示,
避免用两个循环遍历,降低解题难度!
*/
for(int i=n+1;i<=2*n;i++)
{
if((n*i)%(i-n)==0)
printf("1/%d=1/%d+1/%d\n",n,(n*i)/(i-n),i);
}
}
return 0;
}
C 约瑟夫问题
经典约瑟夫环问题,可以百度一下多了解了解
#include <stdio.h>
#include <string.h>
int vis[1005];//记录每一个数是否被输出
int a[1000];//存数字
int main() {
int n, k;
scanf("%d%d", &n, &k);//输入n和k
int cnt = 0;//记录遍历的数的个数
int sum = 0;//记录输出的数的个数
for (int i = 1; i <= n; i++) {
a[i] = i;//初始化
}
int i = 0;
while (sum < n) {
i++;
if(i==n+1) {
i=1;
}
if (vis[a[i]] == 1) {
continue;
}
cnt++;
if (cnt == k) {
vis[a[i]] = 1;
sum++;
cnt = 0;
printf("%d\n",a[i]);
}
}
return 0;
}
D 暴力啥啊
AC代码:
#include <bits/stdc++.h>
using namespace std;
int v[1005][1005];
int main()
{
int n, m;
while (~scanf("%d%d", &n, &m))
{
int ans = 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
scanf("%d", &v[i][j]);
//先存图 ,然后一直在图里面判断最大能炸多少
for (int i = m; i <= n; i++)
{
for (int j = m; j <= n; j++)
{
int sum = 0;
for (int ii = i - m + 1; ii <= i; ii++)
{
for (int jj = j - m + 1; jj <= j; jj++)
{
sum = sum + v[ii][jj];
}
}
if (sum > ans)
ans = sum;
}
}
printf("%d\n", ans);
}
return 0;
}
E n!
本题的数据范围非常的大,光n就1e18了,更别说n的阶乘了,因此直接算出n的阶乘然后进行暴力枚举是不可能的,所以我们需要找规律,我们发现直接用n直接除以3后的商累加,除到不能被3整除为止答案与n的阶乘整除3相同。此题放在防AK的位置上是为了提醒大家,暴力有时候也不是直接上去暴力就能解决问题的,而是通过数学思想的优化,再进行暴力枚举。
FCX学长的解题思路:
AC代码:
#include <stdio.h>
int main()
{
long long int n;
scanf("%lld", &n);
long long int t = 0;
while (n / 3)
{
n /= 3;
t += n;
}
printf("%lld\n", t);
return 0;
}
F Kalevitch and Chess
解题思路:只要这一行有大B就要刷,如果刷了16次,去重刷8次就够了。
AC代码:
#include<stdio.h>
char a[10][10];
int main()
{
int i, j;
for (i = 0; i < 8; i++)
{
scanf("%s", a[i]);//先存图
}
int ans = 0;
for (int i = 0; i < 8; i++)//横向遍历
{
bool f = 1;//每次遍历新的一行的时候 标记初始化
for (int j = 0; j < 8; j++)
{
if (a[i][j] != 'B')//如果等于W就不用粉刷因此让标记等于0
f = 0;
}
if (f)
ans++;
}
//同理的纵向遍历
for (int i = 0; i < 8; i++)
{
bool f = 1;
for (int j = 0; j < 8; j++)
{
if (a[j][i] != 'B')//注意是a[j][i]!!!!
f = 0;
}
if (f)
ans++;
}
if (ans == 16)//去除
ans = 8;
printf("%d\n", ans);
return 0;
}```