B(思维)
题意:扫雷游戏,给定n*m的矩阵两个A和B ,每个矩阵中,‘.’代表这个位置没有东西,‘X’代表这个位置有个地雷,’.‘的分数是以该点为中心的九宫格内所有的雷的数量,整个矩阵的总分是所有’.'的分数总和。
现在我们希望让A和B两个矩阵的分数一样,我们可以改变B矩阵最多不超过n*m/2个点(雷变空or空变雷)。请输出改变后的B矩阵。
思路:一开始我们觉得这个题貌似是一个贡献题,就是算算X的贡献,后来注意到这个鬼数据:n*m/2
我们觉得这么多改变的次数必定有诈,所以试着暴力修改:把所有不一样的点都改成和A一样。但是显然这样不行,但是如果B一开始和A矩阵不一样的点大于nm/2个,那么把A矩阵每个元素都改变得到了A矩阵的逆,就应该有这样的结论:如果A矩阵的B矩阵的不同点个数大于nm/2,那么A的逆矩阵和B的不同点个数一定小于等于n*m/2。
所以输出的就只有两种情况:
1.输出A矩阵
2.输出A的逆矩阵
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
const int N = 1e3+100;
char a[N][N];
char b[N][N];
signed main()
{
cin.tie(0);
cout.tie(0);
ios::sync_with_stdio(0);
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>a[i][j];
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>b[i][j];
int cnt=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(a[i][j]!=b[i][j])
cnt++;
int lim=(n*m)/2;
if(cnt>lim)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(a[i][j]=='.')
cout<<"X";
else
cout<<".";
}
cout<<endl;
}
}
else
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cout<<a[i][j];
}
cout<<endl;
}
}
return 0;
}
G(数学规律,公式)
题意:我们有一个长度为n的斐波那契数列,在求出这个公式的值:
思路:
1.每三项就有一个偶数,所以偶数的个数是n/3
2.每个奇数都可以和每个偶数组合一次,所以方案数有(n-n/3)*(n/3)
3.偶数之间互相组合,推出规律为n *(n-1)/2
所以总方案数为:(n-n/3) *(n/3)+n/3 *(n/3-1)/2
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5+100;
signed main()
{
int n;
cin>>n;
int temp=n/3ll;
cout<<(n-n/3ll)*(n/3ll)+(temp*(temp-1ll))/2ll;
return 0;
}
M(思维,暴力or树的遍历)
题意:给了一堆文件路径,其中前n个文件路径是可以折叠的,后面的m个文件路径不可以折叠,问你折叠之后还剩多少个文件路径
两种做法
1.把不能折叠的路径每一个路径都标记,然后在遍历n个路径的时候检查当前遍历到的路径节点是否被标记为不可折叠,如果是,并且到这个节点之前没有计算过,那么就让答案数加一并且标记一下这个节点被遍历过了。
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
const int N = 200;
map<string,bool>mp,vis;
string a[N];
signed main()
{
cin.tie(0);
cout.tie(0);
ios::sync_with_stdio(0);
int t;
for(cin>>t;t;t--)
{
mp.clear();vis.clear();
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
for(int i=1;i<=m;i++)
{
string s;
cin>>s;
string temp="";
for(int j=0;j<s.length();j++)
{
temp+=s[j];
if(s[j]=='/'||j==s.length()-1)
{
mp[temp]=1;
}
}
}
int ans=0;
for(int i=1;i<=n;i++)
{
string temp="";
for(int j=0;j<a[i].length();j++)
{
temp+=a[i][j];
if(a[i][j]=='/'||j==a[i].length()-1)
{
if(vis[temp])
break;
else if(!mp[temp])
{
vis[temp]=1;
ans++;
break;
}
}
}
}
cout<<ans<<endl;
}
return 0;
}
第二个,给个思路,代码就不写了
我们用类似于字典树的方法来生成这些文件夹的字典树,只不过把字典树的字符换成了字符串(利用map即可完成),然后读入m个不可折叠的文件路径的时候就在树上跑,所经过的点都打上结束标记。做完这些之后只需要统计字典树的叶子节点就可以了。