CCPC-Wannafly Winter Camp Day3 (Div2)

A 二十四点*

【题目】

【解题思路】

这道题暴力搜就好啦...可惜比赛的时候没有时间了并且也不想做了(3个人就坐在那看着这道题 幻想答案会自己跳出来)

至于怎么搜似乎还是需要点技巧?等我会了再放上来

【代码】

F 小清新数论*

【题目】

【解题思路】

这是一道比较基础的数轮题...然而对于数论极差的我来说并不

这道题目我们的思路是先不管莫比乌斯函数,计算\sum_{i=1}^{n}\sum_{j=1}^{n}gcd(i,j),所以我们只要知道在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的对数,实际上就是\left \lfloor \frac{n}{k}\right \rfloor以内gcd为1的对数,这样就可以用欧拉函数求解\left \lfloor \frac{n}{k}\right \rfloor以内gcd为1的对数啦。如果不是很了解欧拉函数的小伙伴可以戳这里。所以最终2*\sum_{i=1}^{\left \lfloor \frac{n}{k} \right \rfloor}\phi (i)-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");
}

猜你喜欢

转载自blog.csdn.net/qq_39826163/article/details/86829631