题解 | #如见青山#
如见青山
https://ac.nowcoder.com/acm/contest/49035/A
A.
可以发现如果 则取模结果一定为。剩下的暴力处理即可
#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.
我这里使用的方式是,将直接赋值成 ,这样 就不可能存在前缀最小值的变化,其余的在排列中按顺序排列,这样最多即有 次前缀最小值的变化
#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.
打表后可以发现,对于 相同的项,除去最后一项,均构成等差数列。(这里我比赛时候脑缠了,一直在找公差的规律,硬是没想到算一下不就完了吗??焯!)。
那么我们可以使用整除分块 在的时间内处理。 对于一个块内的数字,可以先暴力算出首项和末项,即 进制为 和 的情况。使用等差数列公式计算得到答案,再暴力算出进制为 的答案。直接加上即可。
#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. 可以发现无论怎么操作 和 的数量不会改变。且可以全聚到某一个数上。那么直接贪心的将二进制位的 全部堆到最后几个数上就好了
#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;
}