牛客练习赛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; }
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; }
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; }