题解 | #如见青山#

如见青山

https://ac.nowcoder.com/acm/contest/49035/A

A.

可以发现如果 mn! m \le n!则取模结果一定为00。剩下的暴力处理即可

#include<bits/stdc++.h>
using namespace std;
#define int long long
int dp[1000005];
int t,m;
signed main()
{
    cin>>t>>m;
    dp[0] = 1;
    int now = 1;
    int z = 0;
    for(int i = 1;i<=1000000;++i)
    {
        dp[i] = dp[i-1]*i%m;
        now*=i;
        if(now>=m&&!z)
            z = i;
    }
    while(t--)
    {
        int n;
        cin>>n;
        if(n>=z)
        {
            cout<<0<<'\n';
            continue;
        }
        int now = dp[n];
        cout<<dp[now]%m<<'\n';
    }
    return 0;
}

B.

我这里使用的方式是,将QP1Q_{P_1}直接赋值成 11,这样 QQ' 就不可能存在前缀最小值的变化,其余的在排列PP中按顺序排列,这样最多即有 11 次前缀最小值的变化

#include<bits/stdc++.h>
using namespace std;
int n;
int a[1000005];
int b[1000005];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        vector<int> q;
        int now = 1000005;
        for(int i = 1;i<=n;++i)
            cin>>a[i],b[i] = 0;
        int z = a[1];
        b[z] = 1;
        int cnt = 1;
        
        for(int i = 1;i<=n;++i)
        {
            if(b[i])
                continue;
            b[i] = ++cnt;
        }
        for(int i = 1;i<=n;++i)
            cout<<b[i]<<" ";
        cout<<'\n';
                
    }
    return 0;
}

C.

打表后可以发现,对于 n/in/i 相同的项,除去最后一项,均构成等差数列。(这里我比赛时候脑缠了,一直在找公差的规律,硬是没想到算一下不就完了吗??焯!)。

那么我们可以使用整除分块 在n\sqrt{n}的时间内处理。 对于一个块内的数字,可以先暴力算出首项和末项,即 进制为llr1r-1的情况。使用等差数列公式计算得到答案,再暴力算出进制为 rr 的答案。直接加上即可。

#include<bits/stdc++.h>
using namespace std;
#define int long long
int t;
int n;
int check(int n,int l)
{
    int now = n;
    int i = l;
    vector<int> v;
    int ans = 0;
    while(now)
    {
		ans = max(ans,now%i);
		v.push_back(now%i);
		now/=i;
	}
    now = 0;
    ans++;
	for(int i = 0;i<v.size();++i)
		now+=v[i]*pow(ans,i);
    return now;
}
signed main()
{
    cin>>t;
    while(t--)
    {
        cin>>n;
        long long ans = 0;
        for(int l = 2,r;l<=n;l = r+1)
        {
            r = (n/(n/l));
            int l1 = check(n,r);
            ans+=l1;
            if(l==r)
                continue;
            int l2 = check(n,l);
            int l3 = check(n,r-1);
            int xs = (r-l);
            
            ans+=(l2+l3)*xs/2;
        }
        cout<<ans<<'\n';
    }
    return 0;
}

D. 可以发现无论怎么操作 1100 的数量不会改变。且可以全聚到某一个数上。那么直接贪心的将二进制位的 11 全部堆到最后几个数上就好了

#include<bits/stdc++.h>
using namespace std;
int t;
int n;
int a[100005];
int b[100005];
int main()
{
    cin>>t;
    while(t--)
    {
        cin>>n;
        int cnt[31] = {0};
        for(int i = 1;i<=n;++i)
        {
            cin>>a[i];
            for(int j = 0;j<=30;++j)
                if(((a[i]>>j)&1))
                    cnt[j]++;
        }
        for(int i = n;i>=1;--i)
        {
            b[i] = 0;
            for(int j = 0;j<=30;++j)
                if((cnt[j]))
                {
                    cnt[j]--;
                    b[i]|=(1<<j);
                }
        }
        for(int i = 1;i<=n;++i)
            cout<<b[i]<<" ";
        cout<<'\n';
        
    } 
    return 0;
}
全部评论
A题有一个疑问,请问0%m为1吗
点赞 回复
分享
发布于 2022-12-29 11:29 四川
为啥m<=n!则取模结果一定是0?┭┮﹏┭┮
点赞 回复
分享
发布于 2023-02-02 08:52 山东
联易融
校招火热招聘中
官网直投

相关推荐

21 1 评论
分享
牛客网
牛客企业服务