还有牛客小白月赛1 的第I题 是一个卡特兰数的题
还有牛客练习赛 44 小A 的 质数 是关于容斥的一道 忘了 回去看一看呀
A
#incldue <bits/stdc++.h>
using namespace std;
#define ll long long
const long maxn=1e6+5;
const ll mod=1e9+7;
long a[1005][1005];
bool vis[100005];
long n,i,j,sum=0,x,y;
set<long>f;
bool check()
{
f.clear();
for (i=1;i<=n;i++)
{
sum=0;
for (j=1;j<=n;j++)
sum+=a[i][j];
f.insert(sum);
sum=0;
for (j=1;j<=n;j++)
sum+=a[j][i];
f.insert(sum);
}
sum=0;
for (i=1;i<=n;i++)
sum+=a[i][i];
f.insert(sum);
sum=0;
for (i=1;i<=n;i++)
sum+=a[i][n+1-i];
f.insert(sum);
if (f.size()!=2*n+2)
return false;
else
return true;
}
int main()
{
long p,q,x,y,temp;
scanf("%ld",&n);
while (1)
{
sum=0;
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
{
sum++;
a[i][j]=sum;
}
for (i=1;i<=min(n*n,(long)1000);i++)
{
x=rand()%n+1;
y=rand()%n+1;
p=rand()%n+1;
q=rand()%n+1;
temp=a[x][y];
a[x][y]=a[p][q];
a[p][q]=temp;
}
if (check())
{
for (i=1;i<=n;i++)
{
for (j=1;j<n;j++)
printf("%ld ",a[i][j]);
printf("%ld\n",a[i][j]);
}
break;
}
}
return 0;
}
D
第四题 虚虚实实 欧拉回路 欧拉通路
- 使用 欧拉图的充要条件,即 连通图存在欧拉回路当且仅当每个顶点的度为偶数。
连通图存在欧拉通路当且仅当存在 0个或2个 奇度顶点 - 如果不是连通图则不存在题目中的路径,判断连通图有很多方法,例如 并查集,DFS,BFS,传递闭包等 传送门
#include <iostream>
#include <cstring>
using namespace std;
int mapp[35][35],vis[35],sum[35];
int n,m;
void dfs(int v)
{
vis[v]=1;
for(int i=1; i<=n; i++)
{
if(mapp[v][i] && !vis[i])
dfs(i);
}
}
int main()
{
int t;
cin>>t;
while(t--)
{
memset(mapp,0,sizeof(mapp));
memset(vis,0,sizeof(vis));
memset(sum,0,sizeof(sum));
cin>>n>>m;
int u,v;
for(int i=0; i<m; i++)
{
cin>>u>>v;
mapp[u][v]=mapp[v][u]=1;
//计算顶点的度
sum[u]++;
sum[v]++;
}
dfs(1);
bool flag = false;
//判断是否连通
for(int i=1; i<=n; i++)
if(!vis[i])
{
flag = true;
break;
}
if(flag)
cout<<"Xun"<<endl;
else
{
int cnt=0;
//统计奇数定点的个数,如果是 0 || 2 那么就存在欧拉通路
for(int i=1; i<=n; i++)
if(sum[i]&1)
cnt++;
if(cnt==0 || cnt==2)
cout<<"Zhen"<<endl;
else
cout<<"Xun"<<endl;
}
}
return 0;
}
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1005;
int father[maxn];
int t, n , m;
void init()
{
for(int i = 1;i <= n;i ++)
father[i] = i;
}
int getf(int x)
{
if(father[x] == x)
return x;
else
{
father[x] = getf(father[x]);
return father[x];
}
}
void merge(int x,int y)
{
int dx = getf(x);
int dy = getf(y);
if(dx != dy)
father[dy] = dx;
}
int main()
{
cin >> t;
while(t --)
{
cin >> n >> m;
int inout[maxn];
memset(inout,0,sizeof(inout));
int t1,t2;
init();
for(int i = 1;i <= m;i ++)
{
cin >> t1 >> t2;
inout[t1] ++;
inout[t2] ++;
merge(t1,t2);
}
int flag = 0;
for(int i = 1;i <= n;i ++)
{
if(getf(i) == i)
flag ++;
}
if(flag != 1)
cout << "Xun" << endl;
else
{
int point = 0;
for(int i = 1;i <= n;i ++)
{
if(inout[i] % 2 == 1)
point ++;
}
if(point == 0 || point == 2)
cout << "Zhen" << endl;
else
cout << "Xun" << endl;
}
}
return 0;
}
E 博弈
有一些石子堆,第 ii 堆有 ai 个石子。你和算卦先生轮流从任一堆中任取若干颗石子(每次只能取自一堆,并且不能不取),取到最后一颗石子的人获胜。
F 树上博弈
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,r;
vector<int> G[10010];
int vis[10010];
int win(int y)
{
vis[y] = 1;
int d = G[y].size();
if(d == 0)
return 0;
for(int i = 0; i < d; i++)
{
if(vis[G[y][i]] == 1)
continue;
int nxt = win(G[y][i]);//
if(!nxt)
return 1;
}
return 0;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(vis,0,sizeof(vis));
scanf("%d%d",&n,&r);
for(int i = 1; i <= n; i++)
G[i].clear();
int u,v;
for(int i = 0; i < n-1; i++)
{
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
if(win(r))
printf("Gen\n");
else
printf("Dui\n");
}
return 0;
}
G 模拟
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+7;
struct node
{
char s[55];
double N=0;
}p[105];
char temp[N],s[N];
bool cmp(const node a,const node b)
{
if(a.N==b.N)
return strcmp(a.s,b.s)<0;
return a.N>b.N;
}
int main()
{
int n,m;
scanf("%d %d",&n,&m);
scanf("%s",temp);
for (int i=1;i<=m;i++)
{
char name[55];
scanf("%s %s",name,s);
strcpy(p[i].s,name);
int ans=0;
for (int j=0;j<n;j++)
{
if(temp[j]==s[j])
ans++;
}
p[i].N=ans;
}
sort(p+1,p+1+m,cmp);
printf("%s\n%.2lf",p[1].s,100*p[1].N/n);
return 0;
}
H dfs
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 100000+7;
int n,p,k;
vector<pair<int,int> > g[maxn];
int vis[maxn];
ll ans[maxn];
void dfs(int r)
{
vis[r] = 1;
int d= g[r].size();
for(int i = 0; i < d; i++)
{
if(vis[g[r][i].first])
continue;
ans[g[r][i].first] = ans[r]+g[r][i].second;
dfs(g[r][i].first);
}
}
int main()
{
scanf("%d%d%d",&n,&p,&k);//一共有n个点,求从p点出发,第k近的点
int u,v,w;
for(int i = 0; i < n-1; i++)
{
scanf("%d%d%d",&u,&v,&w);
g[u].push_back(pair<int,int>(v,w));
g[v].push_back(pair<int,int>(u,w));
}
dfs(p);
sort(ans+1,ans+n+1);
printf("%d\n",ans[k+1]);
return 0;
}
I 贪心
#include<iostream>
#include<algorithm>
using namespace std;
#define MAX 100005
struct Node {
int st, w;
}a[MAX], b[MAX];
bool cmp(struct Node a,struct Node b) {
return a.st < b.st;
}
int main() {
int n, m, t;
scanf("%d%d%d", &n, &m, &t);
for (int i = 0; i < n; i++)
scanf("%d%d", &a[i].st, &a[i].w);
for (int i = 0; i < m; i++)
scanf("%d%d", &b[i].st, &b[i].w);
sort(a, a + n, cmp);
sort(b, b + m, cmp);
a[n].st = t;
b[m].st = t;
int p1 = 0, p2 = 0, now = 0, pre = 0;
long long ans = 0;
while (p1 < n && p2 < m && now < t) {
int temp = 0;
if (a[p1].w > b[p2].w)
temp = a[p1].w;
else
temp = b[p2].w;
pre = now;
//先设置now再continue
now = min(a[p1 + 1].st, b[p2 + 1].st);
//此处如果写为 temp <=0 continue;则如果全都是负数,死循环
if(temp > 0)
ans = ans + (now - pre)*temp;
if (now == a[p1 + 1].st)
p1++;
if (now == b[p2 + 1].st)
p2++;
}
printf("%lld\n", ans);
return 0;
}