蒟蒻补题ing

河南萌新联赛2024第(四)场:河南理工大学 BCDEFH
(啥也不会,只会暴力555)

B-小雷的神奇电脑

根据同或的定义以及强制的总位数,发现两个数同或结果越大,两个数二进制形式的差异最小

所以从小到大排序即可,遍历一遍对相邻两个数比较

然后不太会别的解决方法,就一位位判断

/*I lv ya*/
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <sstream>
#include <map>
#include <set>
#include <queue>
#include <stdlib.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int N = 2e5+5;
int n,m;
int a[N];
void solve()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    sort(a+1,a+n+1);
    int ans=0;
    for(int i=2;i<=n;i++)
    {
        int tmp=0;
        int x=a[i],y=a[i-1];
        for(int j=1;j<=m;j++)
        {
            if(x%2==y%2)
            {
                tmp+=pow(2,j-1);
            }
            x/=2,y/=2;
        }
        //cout<<ans<<' '<<tmp<<endl;
        ans=max(ans,tmp);
    }
    cout<<ans<<endl;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(NULL),cout.tie(NULL);
    int _;
    _=1;
    while(_--)
    {
        solve();
    }
    return 0;
}

C-岗位分配

很快就发现要用组合数来做,正好早上刚学了组合数的模板(见上一个文章),数据量也不算大

接下来就需要推出是哪个组合数了

根据题意,数组a_i表示的是每个企业至少需要的志愿者,既然是最少也可以多。另外,空闲的志愿者的意思是可以让部分志愿者成为“无业游民”。

题干的最后一句话表示的是志愿者可看作是没有编号的、一模一样的小球-----这说明我们只需要先让所有志愿者满足企业最低需求 sum(a) 后再对剩下的 m-sum(a) 个志愿者进行再分配,此时我们才开始获得答案。

由上我们就知道样例中35是怎么来的了:10-6后还剩4名,这四名可以再分配到3个企业中去,也可以作为“无业游民”。当无业游民的数量为0、1、2、3、4时,我们可得再分配到企业的方式有15+10+6+3+1=35种(可以用隔板法)

改写成组合数就变成了m-sum(a) 个 相同球 放入 n+1 个 不同盒子 里且 能空 的问题

(n+1是因为“无业游民也属于一个盒子”)

只需要每个盒子多加一个小球就变成不能空的问题,即(m+n+1)个球进行隔板法,在本样例中就变成了C(4+3,3),这样这道题就解决了

/*I lv ya*/
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <sstream>
#include <map>
#include <set>
#include <queue>
#include <stdlib.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int N = 2e4+5;
ll n,m;
ll a[N];
const ll md = 998244353;
ll inf[N],fac[N];
ll ksm(ll x, ll y)
{
    ll res=1;
    while(y)
    {
        if(y&1)
            res=res%md*x%md;
        x=x%md*x%md;
        y/=2ll;
    }
    return res;
}
void init()
{
    inf[0]=fac[0]=1;
    for(ll i=1;i<=N;i++)
    {
        fac[i]=fac[i-1]*i%md;
        inf[i]=inf[i-1]*ksm(i,md-2)%md;
    }
}
ll Cf(ll x,ll y)
{
    return fac[x]*inf[y]%md*inf[x-y]%md;
}
void solve()
{
    ll ans=1;
    cin>>n>>m;
    ll sum=0;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        sum+=a[i];
    }
    cout<<Cf(n+m-sum,n)<<endl;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(NULL),cout.tie(NULL);
    int _;
    init();
    _=1;
    while(_--)
    {
        solve();
    }
    return 0;
}

D-简单的素数

暴力判断素数即可,不须筛

bool prime(int x)
{
    if(x<=1)
    {
        return 0;
    }
    for(int i=2;i<=sqrt(x);i++)
    {
        if(x%i==0)
        {
            return 0;
        }
    }
    return 1;
}
void solve()
{
    cin>>n;
    if(prime(n))
    {
        cout<<"Yes"<<endl;
    }
    else
    {
        cout<<"No"<<endl;
    }
}

E-AND

这道题说实话样例给的特别好

首先第一问,我们可以用素数线性筛来筛出2到1e8内的所有素数,用bool存vis,prime数组大概6e6的空间,然后就二分求出a,b的左右区间,l-r得到第一问答案。

第二问有意思,我们发现素数中除了2以外其他数均为奇数,所以没有2存在的子数组不可能相与为0,因为最后一位数永远都是1。然后发现样例到2 5的时候出现了第一组相与为0的子数组,综上判断也是唯一的子数组,之后不论b如何增加都增加prime[c]-prime[5]个子区间(c为最后一个不大于b的素数)

/*I lv ya*/
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <sstream>
#include <map>
#include <set>
#include <queue>
#include <stdlib.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int N = 1e8+3;
int a,b;
bool vis[N];
int prime[6000000],cnt=0;
void prime_xian()
{
    for(int i=2;i<=N;i++)
    {
        if(!vis[i]) prime[++cnt]=i;
        for(int j=1;prime[j]<=N/i;j++)
        {
            vis[prime[j]*i]=1;
            if(i%prime[j]==0) break;
        }
    }
}
void solve()
{
    cin>>a>>b;
    int l=lower_bound(prime+1,prime+cnt+1,a)-prime;
    int r=upper_bound(prime+1,prime+cnt+1,b)-prime;
    cout<<r-l<<' ';
    int ans=0;
    int op=1;
    op<<=r-l;
    //cout<<l<<' '<<r<<endl;
    if(a>2||b<5)
    {
        cout<<0<<endl;
        return ;
    }
    else
    {
        cout<<r-3<<endl;
    }

}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(NULL),cout.tie(NULL);
    int _;
    prime_xian();
    cin>>_;
    while(_--)
    {
        solve();
    }
    return 0;
}

F-小雷的算式

排序后模拟即可

/*I lv ya*/
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <sstream>
#include <map>
#include <set>
#include <queue>
#include <stdlib.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int N = 2e5+5;
string s;
bool cmp(int x,int y)
{
    return x>y;
}
void solve()
{
    cin>>s;
    int len=s.size();
    vector<int>v;
    int ans=0;
    int pos=0;
    while(pos<len)
    {
        int pos2;
        if(s.find("+",pos)!=-1)
            pos2=s.find("+",pos);
        else
            pos2=len;
        //cout<<s.substr(pos,pos2-pos)<<endl;
        v.push_back((int)stoll(s.substr(pos,pos2-pos)));
        pos=pos2+1;
    }
    sort(v.begin(),v.end(),cmp);
    for(int i=0;i<v.size();i++)
    {
        if(i!=v.size()-1)
            cout<<v[i]<<"+";
        else
            cout<<v[i]<<endl;
        ans+=v[i];
    }
    cout<<ans<<endl;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(NULL),cout.tie(NULL);
    int _;
    _=1;
    while(_--)
    {
        solve();
    }
    return 0;
}

H-聪明且狡猾的恶魔

很容易想到只要让一半的恶魔有至少有一个金币就行(一开始判定出问题了就各种阴谋论)

/*I lv ya*/
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <sstream>
#include <map>
#include <set>
#include <queue>
#include <stdlib.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int N = 2e5+5;
int n,x;
void solve()
{
    cin>>x>>n;
    cout<<x-(n-1)/2<<endl;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(NULL),cout.tie(NULL);
    int _;
    cin>>_;
    while(_--)
    {
        solve();
    }
    return 0;
}

剩下的继续补吧....

  • 12
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值