牛客练习赛77

传送门:https://ac.nowcoder.com/acm/contest/11160#question

 

A 小G的sum

题目大意:1-n每个数的最小约数和最大约数之和

题解:这不就是1和它本身么..等差数列求个和 (开long long保平安)

 

B小G的GCD

题目大意:
小G给你两个数n,k
我们定义F(x)为i从1~x i%k==0的i的和
现在希望你求出sum i=1..n F(i) 

题解:推公式

假设n=7,k=3,则需要求 F(1)+F(2)+F(3)+F(4)+F(5)+F(6)+F(7)

F(1)=0 F(2)=0 F(3)=3 F(4)=3 F(5)=3 F(6)=3+6 F(7)=3+6

发现3对>=3的F都有贡献 对答案的贡献为3*(7-3+1),6对>=6的F都有贡献,对答案的贡献为6*(7-6+1)=2*3*(7-2*3+1)

设n以内有gg=n/k个k的倍数,则答案为 sigma(i∈1-gg)i*k*(n-i*k+1) 

#include<bits/stdc++.h>
using namespace std;
int main()
{
    long long n,k,gg,ans=0;
    cin>>n>>k;
    gg=n/k;
    for(int i=1;i<=gg;i++)
    {
        ans=ans+i*k*(n-i*k+1);
    }
    cout<<ans;
    return 0;
}
View Code

 

C小G的约数

题目大意:
小G定义了两个函数F(n)为n的约数和,G(n)为F(1)+F(2)+...+F(n-1)+F(n)
小G想知道G(G(n))等于多少?1<=n<=5e4

题解:约数i出现的次数为 n/i,对答案的贡献为 i*(n/i),这是O(n)的做法

优化方法:整除分块  O(√n)

代码:

#include<bits/stdc++.h>
using namespace std;

#define LL long long

LL n;

LL G(LL x)
{
    LL ans=0;
    for(LL i=1,j;i<=x;i=j+1)
    {
        j=x/(x/i);
        ans=ans+(x/i)*(j-i+1)*(i+j)/2;
    }
    return ans;
}

int main()
{
    cin>>n;
    cout<<G(G(n));    
    return 0;
}
View Code

 

D小G的LY数对

题目大意:
小G定义LY数对为两个数x,y在二进制的异或操作后恰好有两位是1
小G现在有两个数组a,b长度分别为n,m
现在小G想知道有多少对i,j满足
(1<=i<=n,1<=j<=m)满足a[i]和b[j]是LY数对

题解:思维+Hash

假设两个数异或后,只有i位置和j位置为1

x^y=(1<<i)^(1<<j)      (i!=j)

所以x^(1<<i)=y^(1<<j) x^(1<<j)=y^(1<<i)

用hash存a^(1<<i),枚举j,有多少a^(1<<i)与b(1<<j)相等

代码:

#include<bits/stdc++.h>
using namespace std;
#define N 3000008
#define M 10000002
#define MOD 1000007
#define LL long long

int n,m,sume;
LL ans1,ans2;
int head[M],a[N],b[N];
map<int,int>c;

struct Hash
{
    int v,c,nxt;
}e[N];

void Insert(int x)
{
    int k=x%MOD;
    for(int i=head[k];~i;i=e[i].nxt)
    {
        if(e[i].v==x)
        {
            e[i].c++;
            return ;
        }
    }
    e[sume]=Hash{x,1,head[k]};
    head[k]=sume++;
}

int find(int x)
{
    int k=x%MOD;
    for(int i=head[k];~i;i=e[i].nxt)
    {
        if(e[i].v==x) 
        {
            return e[i].c;
        }
    }
    return 0;
}

int main()
{
    cin>>n>>m;
    memset(head,-1,sizeof(head));
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        c[a[i]]++;
    }
    for(int i=1;i<=m;i++)
    {
        cin>>b[i];
        ans2+=c[b[i]]*30;
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<30;j++)
        {
            Insert(a[i]^(1ll<<j));
        } 
    }
    for(int i=1;i<=m;i++)
    {
        for(int j=0;j<30;j++)
        {
            ans1=ans1+find(b[i]^(1ll<<j));
        }
    }
    cout<<(ans1-ans2)/2;
    return 0;
} 
View Code

 

posted @ 2021-03-04 12:43  ANhour  阅读(64)  评论(0编辑  收藏  举报