| 题目 | 难度 | 知识点 |
|---|---|---|
| A 数字方阵 | ★★ | 构造题,shuffle |
| B 小马过河 | ★★ | 计算几何,求垂足 |
| C 真真假假 | ★ | 签到 |
| D 虚虚实实 | ★★ | 欧拉路径 |
| E 是是非非 | ★★ | Nim游戏 |
| F 黑黑白白 | ★★★ | 树上博弈 |
| G 文 | ★ | 模拟 |
| H 武 | ★★ | bfs |
| I 艺 | ★★ | 贪心,模拟 |
| J 美 | ★★ | 构造,贪心 |
数字方阵
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+10;
int a[N][N],n;
int main(void)
{
cin>>n;
int cnt=1;
for(int i=1;i<=n;i++)
for(int j=1;j<=n-1;j++) a[i][j]=cnt++;
for(int i=1;i<=n;i++) a[i][n]=cnt++;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
cout<<a[i][j]<<" ";
}
puts("");
}
return 0;
}
//随机生成的方法,每次随机的生成,生成后写一个check检查合理性即可。
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
const int M=1010;
int a[N],n,b[M][M];
bool check(int a[])
{
map<int,int>mp;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
b[i][j]=a[i*n+j];
for(int i=0;i<n;i++)
{
int sum=0;
for(int j=0;j<n;j++) sum+=b[i][j];
if(mp[sum]) return 0;
mp[sum]++;
}
for(int i=0;i<n;i++)
{
int sum=0;
for(int j=0;j<n;j++) sum+=b[j][i];
if(mp[sum]) return 0;
mp[sum]++;
}
int sum=0;
for(int i=0;i<n;i++) sum+=b[i][i];
if(mp[sum]) return 0;
mp[sum]++;
sum=0;
for(int i=0,j=n-1;i<n;i++,j--) sum+=b[i][j];
if(mp[sum]) return 0;
return true;
}
int main(void)
{
cin>>n;
for(int i=0;i<n*n;i++) a[i]=i+1;
while(1)
{
random_shuffle(a,a+n*n);
if(check(a))
{
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
cout<<a[i*n+j]<<" ";
puts("");
}
break;
}
}
return 0;
}
小马过河
#include <iostream>
#include <cstdio>
using namespace std;
typedef double db;
void solve() {
db x1, y1, x2, y2, x3, y3;
cin >> x1 >> y1 >> x2 >> y2 >> x3 >> y3;
db a = x2 - x3; // 方向向量的x分量
db b = y2 - y3; // 方向向量的y分量
// 计算垂足的y坐标
db y = (b * b * y1 + a * a * y2 - a * b * (x2 - x1)) / (a * a + b * b);
// 计算垂足的x坐标
db x = (a * b * x1 + b * b * y1 - b * b * y) / (a * b);
printf("%.7f %.7f\n", x, y);
}
int main() {
int t = 1, cas = 1;
scanf("%d", &t);
while (t--) {
solve();
}
return 0;
}
#include <iostream>
#include <cstdio>
using namespace std;
int main() {
int T;
cin >> T;
while (T--) {
double Px, Py, Ux, Uy, Vx, Vy;
cin >> Px >> Py >> Ux >> Uy >> Vx >> Vy;
double dx = Vx - Ux; // 方向向量的x分量
double dy = Vy - Uy; // 方向向量的y分量
// 计算参数t
double t = ((Px - Ux) * dx + (Py - Uy) * dy) / (dx * dx + dy * dy);
// 计算垂足坐标
double Qx = Ux + t * dx;
double Qy = Uy + t * dy;
printf("%.10f %.10f\n", Qx, Qy);
}
return 0;
}
这个比较好推,上面的几种数学已经忘完了。
#include <iostream>
#include <cstdio>
using namespace std;
int main() {
int T;
cin >> T;
while (T--) {
double Px, Py, Ux, Uy, Vx, Vy;
cin >> Px >> Py >> Ux >> Uy >> Vx >> Vy;
double A=(Uy-Vy)/(Ux-Vx);
double B=-1;
double C=Vy-(Uy-Vy)/(Ux-Vx)*Vx;
double Qx=(B*B*Px-A*(B*Py+C))/(A*A+B*B);
double Qy=(A*A*Py-B*(A*Px+C))/(A*A+B*B);
printf("%.10f %.10f\n", Qx, Qy);
}
return 0;
}
真真假假
#include<bits/stdc++.h>
using namespace std;
string s[100]={"algorithm", "bitset", "cctype", "cerrno", "clocale", "cmath", "complex", "cstdio", "cstdlib", "cstring", "ctime",
"deque", "exception", "fstream", "functional", "limits", "list", "map", "iomanip", "ios",
"iosfwd", "iostream", "istream", "ostream", "queue", "set", "sstream",
"stack", "stdexcept", "streambuf", "string", "utility", "vector", "cwchar", "cwctype"};
int main(void)
{
int t; cin>>t;
while(t--)
{
int flag=0; string a; cin>>a;
for(int i=0;i<35;i++) if(a==s[i]) flag=1;
if(flag) puts("Qian");
else puts("Kun");
}
return 0;
}
虚虚实实
这里是无向图,故奇的度数要么为0或者2才行,且要所有点联通才行,这样才能经过所有的点。 视频讲解
#include<bits/stdc++.h>
using namespace std;
const int N=1e3;
int p[N],d[N],s[N],t,n,m;
int find(int x)
{
if(x!=p[x]) p[x]=find(p[x]);
return p[x];
}
int main(void)
{
cin>>t;
while(t--)
{
cin>>n>>m;
for(int i=1;i<=n;i++) p[i]=i,s[i]=1,d[i]=0;
while(m--)
{
int a,b; cin>>a>>b;
d[a]++,d[b]++;
if(find(a)!=find(b))
{
s[find(a)]+=s[find(b)];
p[find(b)]=find(a);
}
}
int cnt=0;
for(int i=1;i<=n;i++)
if(d[i]&1) cnt++;
if((cnt==0||cnt==2)&&s[find(1)]==n) puts("Zhen");
else puts("Xun");
}
return 0;
}
是是非非
命题1:当场上所有豆子的异或和非零时,总存在一种方案,可以在一步以内把异或和拿到零。 命题2:当场上所有豆子的异或和为零时,无论怎么拿,异或和不可能从零变成零。 推论:当一个人开始他自己的回合时,如果场上剩下的豆子异或和为0,则这个人必败。
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long int LL;
LL a[N],n,m;
int main(void)
{
cin>>n>>m;
LL sum=0;
for(int i=1;i<=n;i++) cin>>a[i],sum^=a[i];
while(m--)
{
int l,x; cin>>l>>x;
sum=sum^a[l]^x;
a[l]=x;
if(sum) puts("Kan");
else puts("Li");
}
return 0;
}
黑黑白白
就是从叶子开始推,如果说某一个父亲的所有儿子有一个必败的,那该父亲就是必胜的,因为我只要让他往必败走就是我必胜了。
#include<bits/stdc++.h>
using namespace std;
const int N=1e5*2+10;
int h[N],e[N],ne[N],idx;
int st[N],parent[N],t,n,r;//parent[N],从其对应的父亲是谁。
bool ans[N];
vector<int>child[N];//存该点的所有儿子
void add(int a,int b)
{
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void bfs()
{
memset(h,-1,sizeof h); idx=0;
memset(st,0,sizeof st);
memset(parent,0,sizeof parent);
memset(ans,0,sizeof ans);
for(int i=1;i<=n;i++) child[i].clear();
for(int i=0;i<n-1;i++)
{
int a,b; cin>>a>>b;
add(a,b),add(b,a);
}
parent[r]=-1;
queue<int>q;
q.push(r);
while(q.size())
{
int u=q.front(); q.pop();
for(int i=h[u];i!=-1;i=ne[i])
{
int j=e[i];
if(parent[j]==0)
{
parent[j]=u;
child[u].push_back(j);
q.push(j);
}
}
}
for(int i=1;i<=n;i++)
if(child[i].size()==0) q.push(i),st[i]=1;//叶子节点
while(q.size())
{
int u=q.front(); q.pop();
int p=parent[u];
if(p==-1) continue;
for(int i=0;i<child[p].size();i++)//有一个儿子必败,则父亲必胜
if(!ans[u]) ans[p]=1;
bool flag=true;
for(int i=0;i<child[p].size();i++)
if(!st[child[p][i]]) flag=false;
if(flag) q.push(p),st[p]=1;//所有儿子都已经确定好状态了,则入队。
}
if(ans[r]) puts("Gen");
else puts("Dui");
}
int main(void)
{
cin>>t;
while(t--)
{
cin>>n>>r;
bfs();
}
return 0;
}
文
#include<bits/stdc++.h>
using namespace std;
vector< pair<int,string> > ve;
int n,m;
string s;
int main(void)
{
cin>>n>>m>>s;
for(int i=0;i<m;i++)
{
string name,s1; cin>>name>>s1;
int cnt=0;
for(int j=0;j<n;j++) if(s1[j]==s[j]) cnt++;
ve.push_back({n-cnt,name});
}
sort(ve.begin(),ve.end());
cout<<ve[0].second<<endl;
printf("%.2lf",(n-ve[0].first)*1.0/n*100);
return 0;
}
武
#include<bits/stdc++.h>
using namespace std;
const int N=1e5*2+10;
int h[N],e[N],w[N],ne[N],idx;
int d[N],n,p,k,st[N];
void add(int a,int b,int c)
{
e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
void dfs(int u,int s)
{
d[u]=s,st[u]=1;
for(int i=h[u];i!=-1;i=ne[i])
{
int j=e[i],ww=w[i];
if(!st[j])
{
dfs(j,s+ww);
}
}
}
int main(void)
{
cin>>n>>p>>k;
memset(h,-1,sizeof h);
for(int i=0;i<n-1;i++)
{
int a,b,c; cin>>a>>b>>c;
add(a,b,c),add(b,a,c);
}
memset(d,-1,sizeof d);
dfs(p,0);
sort(d+1,d+1+n);
cout<<d[k+1]<<endl;
return 0;
}
艺
可以不看,注意一下。
#include<bits/stdc++.h>
using namespace std;
typedef long long int LL;
int n,m,t;
vector< pair<LL,LL> >ve1,ve2;
int main(void)
{
cin>>n>>m>>t;
for(int i=0;i<n;i++)
{
int x,v; cin>>x>>v;
ve1.push_back({x,v});
}
for(int j=0;j<m;j++)
{
int x,v; cin>>x>>v;
ve2.push_back({x,v});
}
sort(ve1.begin(),ve1.end());
sort(ve2.begin(),ve2.end());
LL ans=0;
LL p1=0,p2=0,temp1,temp2;
for(int i=1;i<=t;i++)
{
if(p1<n&&ve1[p1].first<i) temp1=ve1[p1].second,p1++;
if(p2<m&&ve2[p2].first<i) temp2=ve2[p2].second,p2++;
ans+=max({0ll,temp1,temp2});
}
cout<<ans;
}
美
#include<bits/stdc++.h>
using namespace std;
const int N=1e5*2+10;
typedef long long int LL;
LL a[N],s[N],c[N],n;
int main(void)
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
sort(a+1,a+n+1);
int mid=n/2;
int i=1,j=n,k=1;
while(i<=mid&&j>=mid+1)
{
c[k++]=a[j--];
c[k++]=a[i++];
}
while(i<=mid) c[k++]=a[i++];
while(j>=mid+1) c[k++]=a[j--];
s[1]=abs(c[1]-c[n]);
for(int i=2;i<=n;i++)
{
s[i]+=s[i-1]+abs(c[i]-c[i-1]);
}
cout<<s[n]<<endl;
return 0;
}