A 二十四点*
【题目】
【解题思路】
这道题暴力搜就好啦...可惜比赛的时候没有时间了并且也不想做了(3个人就坐在那看着这道题 幻想答案会自己跳出来)
至于怎么搜似乎还是需要点技巧?等我会了再放上来
【代码】
F 小清新数论*
【题目】
【解题思路】
这是一道比较基础的数轮题...然而对于数论极差的我来说并不
这道题目我们的思路是先不管莫比乌斯函数,计算,所以我们只要知道在i=1-n和j=1-n范围内gcd(i,j)=k的对数,那么在1-k范围内累加μ(k)*k的对数即可。
那么k的对数怎么求呢,首先需要明确的是gcd(i,j)=k和gcd(j,i)=k是不同的,但是i=j的情况只算一次,所以gcd(i,j)=k的对数实际上应该是数对的对数*2-1。
那么n以内gcd为k的对数,实际上就是以内gcd为1的对数,这样就可以用欧拉函数求解以内gcd为1的对数啦。如果不是很了解欧拉函数的小伙伴可以戳这里。所以最终即是我们需要求的对数。
【代码】
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn=1e7+5;
LL ans;
LL fac[maxn]; //(a<=n,b<=m)范围内gcd=i的对数(筛选:i的倍数都应该减掉)
int mu[maxn];
const int mod=998244353;
LL cnt,prime[maxn],vis[maxn],phi[maxn];
void get_mu(int n)
{
memset(vis,0,sizeof(vis));
memset(prime,0,sizeof(prime));
memset(mu,0,sizeof(mu));
cnt=0;
mu[1]=1;vis[1]=1;
phi[0]=0;phi[1]=1;
for(int i=2;i<=n;i++)
{
if(!vis[i])
{
prime[++cnt]=i;
phi[i]=i-1; //欧拉函数
mu[i]=-1;//莫比乌斯函数
}
for(int j=1;j<=cnt && prime[j]*i<=n;j++)
{
vis[prime[j]*i]=1;
if(i%prime[j]==0)
{
mu[prime[j]*i]=0;
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
mu[prime[j]*i]=-mu[i];
phi[i*prime[j]]=phi[i]*(prime[j]-1);
}
}
for(int i=1;i<=n;i++)phi[i]+=phi[i-1];
for(int i=1;i<=n;i++)fac[i]=2*phi[n/i]-1;
}
int main()
{
int n,m,p,T;
ans=0;
scanf("%d",&n);
get_mu(n);
LL ans=0;
for(int i=1;i<=n;i++){
ans+=(mu[i]*fac[i]+mod)%mod;
ans%=mod;
}
printf("%lld\n",ans);
return 0;
}
G 排列
【题目】
【解题思路】
签到题,理解题目就好啦。
p:原数组
Ap:前缀数组
q:p中第i小的前缀的长度,也就是Ap中第i大的位置
由此可以得出有些位置是能够被确定的,先把这些位置确定下来,其他就好做了。
【代码】
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
const int INF=0x3f3f3f3f;
int p[maxn],q[maxn];
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&q[i]);
q[0]=INF;
int cnt=1;
for(int i=1;i<=n;i++)
{
if(q[i]<q[i-1])p[q[i]]=cnt++;
}
for(int i=1;i<=n;i++)
{
if(p[i]==0)p[i]=cnt++;
}
printf("%d",p[1]);
for(int i=2;i<=n;i++)printf(" %d",p[i]);
printf("\n");
}