河南萌新联赛2024第(二)场:南阳理工学院
“好”字符
1.使用字符串哈希来解决问题。
2.我们模拟样例来解决问题
\(a=acabxb,b=eababf,把a中出现过的字符放进set里,便于后面的遍历\)\(令b=eababfeababf,这样相当于模拟了循环同构。然后在我们遍历set里的\)
\(字母时,比如遍历a,我们相当于令字符串中的a为1,其余为0,此时对应的01串\)
\(为b=010100010100,这是我们脑袋中想象的过程,实现的过程中只需要统计到\)
\(每个位置的字符串的对应哈希值,比如遍历到0,01,010,0101......的位置的哈希值\)
\(此时的a=101000,a有一个对应的哈希值,那么相当于在b上移动一个长度为n的区间,\)
\(然后看这段区间的字符串的哈希值是不是跟a的哈希值相当即可\)
#include <bits/stdc++.h>
//#define int long long
#define endl '\n'
using namespace std;
typedef pair<int,int> pii;
#define x first
#define y second
#define all(v) v.begin(),v.end()
#define ull unsigned long long
ull P=131;
ull pm[2000005],hb[1000005],ha[2000005];
void brdkhash(string s,char c,ull *h)
{
for(int i=1;i<s.size();i++) h[i]=h[i-1]*P+(s[i]==c);//对应位置字符串的哈希
}
ull getx(ull *h,int l,int r){
return h[r]-h[l-1]*pm[r-l+1];//计算区间字符串的哈希
}
void solve()
{
int n; cin>>n;
string a,b; cin>>a>>b;
set<char>se(all(a));
a=' '+a+a;//起点设为1,方便计数
b=' '+b;
pm[0]=1;
for(int i=1;i<=2000005;i++) pm[i]=P*pm[i-1];//方便计算
int ans=0;
for(auto t:se)
{
brdkhash(a,t,ha);
brdkhash(b,t,hb);
for(int i=1;i<=n;i++)
{
if(getx(ha,i,i+n-1)==getx(hb,1,n)){
ans++;
break;
}
}
}
cout<<ans;
}
signed main()
{
ios::sync_with_stdio(0),cin.tie(0);
int t=1;
//cin>>t;
while(t--) solve();
}
这是签到
套个算行列式的板子,然后算出所有的值比较即可,如果n和m不同,记得把最后的结果和0比较
#include <iostream>
using namespace std;
const int MAXN = 7;
int det(int a[MAXN][MAXN], int n) {
int res = 0;
if (n == 1) {
return a[0][0];
} else {
for (int j = 0; j < n; j++) {
int t[MAXN][MAXN];
for (int i = 1; i < n; i++) {
int k = 0;
for (int p = 0; p < n; p++) {
if (p == j) {
continue;
}
t[i - 1][k++] = a[i][p];
}
}
res += ((j % 2 == 1) ? -1 : 1) * a[0][j] * det(t, n - 1);
}
}
return res;
}
int main() {
ios::sync_with_stdio(0),cin.tie(0);
int n,m;
cin >> n>>m;
int minn=1e9;
if(n!=m) minn=min(n,m);
else minn=n;
int a[MAXN][MAXN];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cin >> a[i][j];
}
}
int ans=1e9;
for(int i=1;i<=minn;i++)
{
ans=min(det(a,i),ans);
}
if(n!=m) cout<<min(ans,0);
else cout<<ans;
return 0;
}
狼狼的备忘录
1.多开几个map存对应信息即可。
我的错误数据:
点击查看代码
in
20
l 6 02 02 2 02 02 2
l 8 8 8 8 2 62 13 31 3
e 9 0 91 0 0 60 91 60 2 44
e 9 69 2 1 44 2 91 66 1 70
l 9 7 27 27 3 1 3 7 80 81
l 9 2 1 13 7 2 10 02 3 92
e 9 0 15 3 5 5 15 91 09 44
l 7 2 50 4 5 98 31 98
l 3 26 7 3
e 6 7 5 0 62 65 91
l 8 80 0 4 0 2 2 0 13
l 9 19 13 02 2 1 4 19 26 02
l 10 7 39 7 9 22 22 26 2 90 4
e 7 65 2 36 0 34 57 9
e 8 13 02 09 91 73 5 36 62
l 9 75 0 10 8 76 7 82 8 34
l 7 34 0 19 80 6 4 7
e 5 4 2 5 7 2
e 7 4 02 69 7 07 20 2
l 4 8 2 1 63
out:
2
e 18 02 07 09 13 15 20 34 36 44 57 60 62 65 66 69 70 73 91
l 21 02 10 13 19 22 26 27 31 34 39 50 62 63 75 76 80 81 82 90 92 98
题解代码
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
typedef pair<int,int> pii;
#define x first
#define y second
#define all(v) v.begin(),v.end()
void solve()
{
int n; cin>>n;
map<string,set<string> >mp;//放答案
map<string,vector<string> >fi;//放各自的星座信息
map<string,int>che;//用来去重,实现规则A
set<string>na;//存出现过的名字
for(int i=0;i<n;i++)
{
string s; cin>>s;
na.insert(s);
int x;cin>>x;
while(x--)
{
string sb;
cin>>sb;
fi[s].push_back(sb);
}
}
//全部放完以后在去去后缀,不然会有那个样例的错误
for(auto t:na)
{
che.clear();
for(auto k:fi[t])
{
for(int i=1;i<k.size();i++)
{
string ss=k.substr(i);
che[ss]=1;
}
}
for(auto k:fi[t]) {
if(che[k]!=1) mp[t].insert(k);
}
}
cout<<mp.size()<<endl;
for(auto t:mp)
{
cout<<t.first<<" ";
cout<<t.second.size()<<" ";
vector<string>ans;
for(auto k:t.second)
{
ans.push_back(k);
}
cout<<ans[0];
if(ans.size()>1) for(int i=1;i<ans.size();i++) cout<<" "<<ans[i];
cout<<endl;
}
}
signed main()
{
ios::sync_with_stdio(0),cin.tie(0);
int t=1;
//cin>>t;
while(t--) solve();
}
lxy的通风报信
1.使用bfs寻找每一个\(*\) 到其他\(*\)的距离,然后使用最小生成树算法,即可得到答案
2.但是细节非常多,注意bfs中细节的处理。
#include <bits/stdc++.h>
//#define int long long
#define endl '\n'
using namespace std;
typedef pair<int,int> pii;
#define x first
#define y second
#define all(v) v.begin(),v.end()
#define ull unsigned long long
int dx[]={0,1,0,-1};
int dy[]={1,0,-1,0};
map<pii,int>mp;//给每个点编号
int n,m,ans,cnt;
bool tmp;
char c[1005][1005];
int f[1000005];
typedef struct{
int from;//起点
int to;//终点
int dis;//距离
}road;
//-------------------------------------
//最小生成树算法的一部分
bool cmp(road a,road b)
{
return a.dis<b.dis;
}
int find(int x){
return f[x]==x?x:f[x]=find(f[x]);
}
//--------------------------------------
vector<road>ve;//放哪个点到哪个点的序号,和它们之间的距离
void bfs(int xx,int yy)
{//bfs计算每个结点到其他结点的距离
queue<pii>q;
q.push({xx,yy});
int start=mp[{xx,yy}];//该起点的位置
int foot[1005][1005]={0};//记录步数
while(!q.empty())
{
auto t=q.front();
q.pop();
for(int i=0;i<4;i++)
{
int a=t.x+dx[i],b=t.y+dy[i];
if(a>=1&&a<=n&&b>=1&&b<=m&&c[a][b]!='#'&&foot[a][b]==0)
{
q.push({a,b});
foot[a][b]=foot[t.x][t.y]+1;//记得放if外面,不然会死循环
if(c[a][b]=='*') {
ve.push_back({start,mp[{a,b}],foot[a][b]});
}
}
}
}
}
signed main()
{
ios::sync_with_stdio(0),cin.tie(0);
cin>>n>>m;
int id=1;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++) {
cin>>c[i][j];
if(c[i][j]=='*')
mp[{i,j}]=id++;
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(c[i][j]=='*') bfs(i,j);
}
}
//-----------------------------------------------
//最小生成树算法 kruskal算法
sort(all(ve),cmp);
for(int i=1;i<=1000005;i++) f[i]=i;
for(int i=0;i<ve.size();++i){
int fx=find(ve[i].from),fy=find(ve[i].to);
if(fx==fy) continue;
f[fy]=fx;
ans+=ve[i].dis;
++cnt;
if(cnt==mp.size()-1){
tmp=1;
break;
}
}
if(tmp) cout<<ans;
else cout<<"No";
//------------------------------------------
}
posted on 2024-07-25 16:33 swj2529411658 阅读(48) 评论(0) 编辑 收藏 举报