蓝桥杯国赛2022A组
蓝桥杯国赛 2022 A组:
A题
这一题就是数学,首先答案应该是C(28,14)*(剩下14个学生排列组合,每个人都没拿到自己的钥匙的情况总数)前面是组合数。
如果上一句话看不懂可以弃赛了。
所以说我们这里简化表达,i个学生排列组合,每个人都没拿到自己的钥匙的情况总数为xi,则
x1=0,x2=1.为了最后结果设x0=1
则正推式子:
x3=3!-[c(3,1)x2+c(3,2)x1+c(3,3)x0];//因为要加上全部相同的那一种,所以x0=1
找规律得出通式:
xi=i!-[c(i,1)x_i-1+c(i,2)x_i-2+...+c(i,i)x0];
所以可以用以下代码求解:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll x[109];
ll f[109];
ll c(ll n,ll m)
{
return f[n]/f[m]/f[n-m];
}
int main()
{
x[0]=1;
x[1]=0;
x[2]=1;
f[0]=1;
f[1]=1;
for(ll i=2;i<=14;i++)
{
f[i]=f[i-1]*i;
}
for(ll i=3;i<=14;i++)
{
x[i]=f[i];
for(ll j=1;j<=i;j++)
{
x[i]-=(c(i,j)*x[i-j]);
}
// cout<<i<<":"<<x[i]<<endl;
}
ll ans=1;
for(ll i=15;i<=28;i++)
{
ans*=i;
}
// cout<<ans/f[14]<<" "<<x[14]<<endl;
cout<<ans/f[14]*x[14]<<endl;
return 0;
}
B 题
C题:
这题在洛谷是绿题,其实不应该,就是判断策略麻烦了一些。
#include<bits/stdc++.h>
using namespace std;
//const
string s;
typedef long long ll ;
ll fin_sum[7];
string t[4];
int main()
{
int n;
cin>>n;
ll sum=0,q;
getchar();
for(int i=0;i<n;i++)
{
getline(cin,s);
string s1 = s.substr(0,6);
int len=s.size();
if(s1 == "String")
{
int pos=0;
while(pos<len)
{
if(s[pos]=='=')
{
pos+=2;
while(s[pos]!='"')
{
sum++;
pos++;
}
}
pos++;
}
}
else
{
if(s.substr(0,3)=="int")q=4;
else q=8;
int w = s.find("[");
if(w<0)
{
for(int j=0;j<len;j++)
{
if(s[j]=='=')sum+=q;
}
}
else
{
int pos=0;
while(pos<len-1)
{
if(s[pos]=='['&&s[pos+1]!=']')
{
pos++;
ll ans=0;
while(s[pos]!=']')
{
ans=ans*10+s[pos]-'0';
pos++;
}
sum+=ans*q;
}
pos++;
}
}
}
}
// cout<<sum<<endl;
for(int i=3;i>0;i--)
{
fin_sum[i]=sum%1024;
sum/=1024;
}
fin_sum[0]=sum;
t[0]="GB";
t[1]="MB";
t[2]="KB";
t[3]="B";
for(int i=0;i<4;i++)
{
if(fin_sum[i]==0)continue;
cout<<fin_sum[i]<<t[i];
}
cout<<endl;
return 0;
}
/*
先特判string的,找双引号内的字符
然后找其它类型的,等于号后面的数字,如果等于号后面是[就把[]里的数字算进去
*/
B组D题凑数:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll s[20],t[20];
ll maxx=-1;
int num=0;
void dfs(ll pos,ll a,ll b)
{
if(pos==0)
{
ll sum=0;
for(int i=num;i>=1;i--)
{
sum=sum*10+t[i];
maxx=max(maxx,sum);
}
return ;
}
//全加
ll add = s[pos]+min(9-s[pos],a);
ll sub = (b>=s[pos]+1)?9:s[pos];
ll cha=0;
if(sub==9&&s[pos]!=9)cha=s[pos]+1;
if(add>sub)
{
t[pos]=add;
dfs(pos-1,a-min(9-s[pos],a),b);
}
else if(sub>add)
{
t[pos]=sub;
dfs(pos-1,a,b-cha);
}
else
{
t[pos]=add;
dfs(pos-1,a-min(9-s[pos],a),b);
for(int i=1;i<pos;i++)t[i]=s[i];
dfs(pos-1,a,b-cha);
for(int i=1;i<pos;i++)t[i]=s[i];
}
}
void f(ll n,ll a,ll b)
{
while(n)
{
s[++num]=n%10;
t[num]=n%10;
n/=10;
}
dfs(num,a,b);
}
int main()
{
ll n,a,b;
cin>>n>>a>>b;
f(n,a,b);
cout<<maxx<<endl;
return 0;
}
/**
每一位要么全加要么全减,贪心的从前往后操作,如果全加大就选全加,如果全减大就选全减,如果这俩一样大就拉分支。
*/
F题:
这一题考察的应该是floyd最短路和二分查找。
因为对于天数是一个01数组,天数少了不满足,天数多了满足。所以可以用二分查找去解决问题。然后就暴力生成每一个天数的数组状态,然后用floyd最短路跑出来。
比较难搞的一个是上限问题,可以看题目的最大数据范围和下限的差值最多为1e5,然后n又不超过100,所以天数不会超过1e7。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 109;
ll a[N][N],c[N][N];
ll ch[N][N];
int n;
ll q;
bool check(int x)//第x天
{
memcpy(ch, a, sizeof(a));
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
ll cha = x/n+(x%n>=i?1:0);
if(ch[i][j]-cha>=c[i][j])
{
ch[i][j]-=cha;
ch[j][i]-=cha;
}
else
{
ch[i][j]=c[i][j];
ch[j][i]=c[i][j];
}
}
}
for(int k=1; k<=n; k++)//k必须在最外层
{
for(int j=1; j<=n; j++)
{
for(int i=1; i<=n; i++)
{
if(ch[i][j]>ch[i][k]+ch[k][j])
{
ch[i][j]=ch[i][k]+ch[k][j];
}
}
}
}
ll ans =0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
ans+=ch[i][j];
}
}
return (ans<=q);
}
int main()
{
cin>>n>>q;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
cin>>a[i][j];
}
}
ll sum=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
cin>>c[i][j];
sum+=c[i][j];
}
}
int l=0,r=1e7,mid;
while(l<=r)
{
mid=(l+r)/2;
if(check(mid))
r=mid-1;
else l=mid+1;
}//0000111
if(l>1e7)l=-1;
cout<<l<<endl;
return 0;
}
G题
倒着来推,首先最终的数一定是某个素数的倍数。
先找出n的所有质因数。
#include<bits/stdc++.h>
using namespace std;
const int N =1e8+103;
typedef long long ll;
int vis[N];
ll prime[N];
int cnt=0;
void oula()
{
vis[0]=1;
vis[1]=1;
for(int i=2; i<=2000009; i++)
{
if(!vis[i])
{
prime[cnt++]=i;
}
for(int j=0;j<cnt&&(ll)i*(ll)prime[j]<=2000009;j++)
{
vis[i*prime[j]]=1;
if(i%prime[j]==0)break;
}
}
}
ll get_maxprime(ll x)
{
ll k=x;
ll maxx=-1;
for(int i=0;prime[i]*prime[i]<=x;i++)
{
while(x%prime[i]==0)
{
x/=prime[i];
if(prime[i]<k)maxx=max(maxx,prime[i]);
}
}
if(x>1&&x<k)maxx=max(maxx,x);
return maxx;
}
int main()
{
oula();
ll n;
cin>>n;
ll net=get_maxprime(n);
if(net==-1)
{
cout<<-1<<endl;
return 0;
}
ll one = n-net+1;
ll minn = N;
for(ll i=one;i<=n;i++)
{
ll k = get_maxprime(i);
if(k!=-1)
{
minn=min(minn,i-k+1);
}
}
if(minn==N)minn=-1;
cout<<minn<<endl;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!