蓝桥杯国赛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;
}
posted @   wlqtc  阅读(18)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示