最近刚打完吉林省程序设计竞赛,自己比较菜,成绩不是很好,拖累了两位队友,其中一位队友保研,并在比赛前一天拿到了百度的实习offer.另一位是备战考研。
比赛只过了A,B,E,L,M,最终41名
A题:
题目大意:给你一i个数组,判断数组中元素奇数和偶数的个数差是否小于等于1.
签到题
//
// Created by LiuHongzhe on 2021/11/30.
//
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n;
ll ans;
ll x;
ll dx,dy;
int main()
{
ll i,j,k;
cin>>n;
for(i=0;i<n;i++)
{
cin>>x;
if(x%2==0)
dx++;
else
{
dy++;
}
}
ans=abs(dx-dy);
if(ans<=1)
{
cout<<"Good"<<endl;
}else
{
cout<<"Not Good"<<endl;
}
return 0;
}
B题:
题目大意:给三个数a,b,k,计算a/b,保留k位
签到题
//
// Created by LiuHongzhe on 2021/11/30.
//
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
ll i,j;
ll a, b,k;
ll t;
cin>>a>>b>>k;
if(a==b)
{
cout<<"1.";
for(i=0;i<k;i++)
{
cout<<0;
}
} else{
cout<<"0.";
for(i=0;i<k-1;i++)
{
t=a*10/b;
cout<<t;
a=a*10%b;
}
ll dt=a*10/b;
a=a*10%b;
t=a*10/b;
if(t>=5&&t<=9)
{
cout<<dt+1;
}
else
{
cout<<dt;
}
}
return 0;
}
E题:
给一个数组,判断是否存在两个元素异或等于1
a[i]^a[j]==1&&i!=j
a[i]^a[j]==1&&i!=j
基础知识:
1^1=0;1^0=1;0^1=1;0^0=0;
若a^b=c则 c^a=(a^b)^a=b
则原题可以推理为是否存在a[i]^1属于数组中的元素
//
// Created by LiuHongzhe on 2021/11/30.
//
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll t,n;
ll flag;
int main()
{
ll i,j;
ll x;
cin>>t;
while(t--)
{
set<ll>a;
flag=false;
n = 0;
scanf("%lld", &n);
for(i=0;i<n;i++)
{
scanf("%lld", &x);
a.insert(x);
}
for(auto it:a)
{
ll dt=it^1;
ll dx=a.count(dt);
if(dx==1)
{
flag=true;
break;
}
}
if(flag)
{
printf("Yes\n");
}else
{
printf("No\n");
}
}
return 0;
}
L题:
题目大意:给一个字符串S,定义Si为从S的第i位开始的子串,Si有两种处理办法,一种删去最后一个字符,另一种加入一个字符,最后让Si构造成S的最小次数记位d(Si),求d(Si)中最大的数
//
// Created by LiuHongzhe on 2021/11/30.
//
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
int t;
cin >> t;
string s;
while(t--) {
cin >> s;
int i;
const int sz = s.size();
for(i = 1; i < sz; ++i) {
if(s[i] == s[i - 1]) continue;
else break;
}
if(i == sz) cout << sz - 1 << endl;
else cout << sz * 2 - i << endl;
}
return 0;
}
M题:
题目大意:给一个数组,求数组的极差与数组长度的乘积。
签到题
//
// Created by LiuHongzhe on 2021/11/30.
//
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n;
ll a[10005];
ll maxn = -100005;
ll minn = 100005;
int main()
{
cin >> n;
for(int i = 0; i < n; i++ ){
cin >> a[i];
maxn = max(maxn, a[i]);
minn = min(minn, a[i]);
}
ll ans = maxn - minn;
ans *= n;
cout << ans << endl;
return 0;
}
后面题目,比赛中没有做对,比赛结束自己补的,不能保证一定正确
K题:
题目大意:求给定一个长度位2N,括号种类位K的合法的括号数量
对于只有一种括号时,括号的数量是卡特兰数列
对于k种括号时,答案就是卡特兰数列*(k^n)
卡特兰数,应用于:括号化,凸多边形三角划分,给定节点组成二叉搜索树,n对括号正确匹配数目。
此题考查了数学知识:排列组合,快速幂,卡特兰数列
其中排列组合在曾在热身赛中第二题出现过
//
// Created by LiuHongzhe on 2021/11/30.
//
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n;
ll k;
ll N=1e9+7;
ll ans;
ll fastpow1(ll a, ll n) {//快速幂
ll base = a;
ll res = 1;
while(n) {
if(n & 1)
res = (base * res) % N;
base = (base * base) % N;
n >>= 1;
}
return res;
}
ll fun(ll n,ll m)//排列组合
{
if(m==0)
return 1;
ll a[n+5];
for(int i=1;i<=n;i++)
{
a[i]=i;
}
for(int j=2;j<=m;j++)
{
ll t=j;
for(int i=n-m+1;i<=n;i++)
{
if(__gcd(t,a[i])>1)
{
ll dy=__gcd(t,a[i]);
a[i]=a[i]/dy;
t=t/dy;
if(t==1)
break;
}
}
}
ll sum=1;
for(int i=n-m+1;i<=n;i++)
{
sum=(sum*a[i])%N;
}
return sum;
}
int main()
{
cin>>n>>k;
ll x1= fastpow1(k,n);
ll x2= fun(2*n,n);
ll x3=fun(2*n,n-1);
x3=(x2+N-x3)%N;
ans=(x3*x1)%N;
cout<<ans;
return 0;
}
H题:
根据给出的路径,计算每条边权的期望值,然后求和,结果在用费马小定理处理
费马小定理:
b/a mod p
==>b*a^-1 mod p
==> b*a^p-2 mod p
此代码在处理期望部分可能存在bug,(对于分布期望不会求解。。。。。)
//
// Created by LiuHongzhe on 2021/11/30.
//
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,m,k;
ll x,y,z;
int b[300005];
ll ans;
ll N=998244853;
vector<vector<vector<ll>>>cnt;
ll fastpow1(ll a, ll n) {//快速幂
ll base = a;
ll res = 1;
while(n) {
if(n & 1)
res = (base * res) % N;
base = (base * base) % N;
n >>= 1;
}
return res;
}
void method01(){
ll i,j;
for(i=0;i<=n;i++)//打表
{
vector<vector<ll>>cnt1;
for(j=0;j<=i;j++)
{
vector<ll>cnt2;
cnt1.push_back(cnt2);
}
cnt.push_back(cnt1);
}
ll u,v,w;
for(i=0;i<m;i++)//数据录入
{
cin>>u>>v>>w;
if(u<v)
swap(u,v);
cnt[u][v].push_back(w);
}
}
void method02(){
ll i;
for(i=0;i<k;i++)
{
cin>>b[i];
}
}
void method03(){//求x,y
ll i,j;
ll sum=1;
y=1;
for(i=k-1;i>0;i--)
{
ll dx=b[i];
ll dy=b[i-1];
if(dx<dy)
swap(dx,dy);
ll len=cnt[dx][dy].size();
y=(y*len)%N;
if(len==0)
{
cout<<"Stupid Msacywy!"<<endl;
exit(0);
}
}
x=0;
for(i=k-1;i>0;i--)
{
ll dx=b[i];
ll dy=b[i-1];
if(dx<dy)
swap(dx,dy);
ll add=0;
for(j=0;j<cnt[dx][dy].size();j++)
{
add=add+cnt[dx][dy][j];
}
ll len=cnt[dx][dy].size();
ll de=(add*sum*y/len)%N;
x=(x+de)%N;
sum=(sum*10)%N;
}
}
void method04(){
// x/y;
ll ans=fastpow1(y,N-2);
ans=(ans*x)%N;
cout<<ans;
}
int main()
{
cin>>n>>m>>k;
method01();
method02();
method03();
method04();
return 0;
}
C题:
题目大意:给定x0;且xn=(a*x(n-1)+b)%m;是否存在xi是给定的一个数(给定的数<m)
此题涉及线性同余方程求解和BSGS算法
然后自己手动推理了一下公式的转化
G题:
题目大意:给一个01矩阵(其中空缺位置为-1)和每行每列的异或值,复原此矩阵。
用到同E题的异或性质,做法类似玩数独游戏,每次对某行或者某列只有一个未知元素的优先处理。既先对处理位置做一个拓扑排序,然后依次处理即可。(但我不会写拓扑排序。。。)
后面补题后更新
下面是官方简要题解和省赛原题
链接:https://pan.baidu.com/s/1e5w2P6tbPSmR-NfazYdXNA
提取码:uwd9
比赛终榜