【bestcoder #39】CD例题
Code
Accepts: 125 Submissions: 736
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
问题描述
wld有一个长度为n的序列a1..an
wld想要你给出下面这段c++代码的输出:
int calc()
{
int res=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
res+=gcd(a[i],a[j])*(gcd(a[i],a[j])-1);
res%=10007;
}
return res;
}
保证1≤n≤10000,1≤ai≤10000 (对于任意1≤i≤n)
输入描述
多组数据(最多10组)
对于每组数据:
第一行:一个数n表示序列的长度
第二行:n个数,依次为a1,a2,…,an
输出描述
对于每组数据:
输出calc函数的返回值
输入样例
5
1 3 4 2 4
输出样例
64
Hint
gcd(i,j)为两数的最大公因数。
两种做法,先说一种简单的:
①首先对于每一个数字
②我们要考虑的问题是如果两个数都含有因数4,他们在2和4中都出现了,而只需要算4的这一次,为了处理这种情况,我们从大到小枚举因数:
最大的因数必然不会产生上述问题;
对于较小的数
第二种做法用到了莫比乌斯反演:
如果是求
注:
变成了求
假设
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <map>
#include <vector>
#include <iostream>
#include <set>
#include <cmath>
#define mod 10007
#define LL long long
#define M 10000
#include <vector>
#define pb push_back
using namespace std;
vector<int> c[M+5];
int v[M+5],f[M],mu[M+5],tot,cnt[M+5],p[M],n;
void Getmobius()
{
mu[1]=1;
for (int i=2;i<=M;i++)
{
if (!v[i])
{
p[++tot]=i;
mu[i]=-1;
}
for (int j=1;j<=tot;j++)
{
if (i*p[j]>M) break;
v[i*p[j]]=1;
if (i%p[j]==0)
{
mu[i*p[j]]=0;
break;
}
else mu[i*p[j]]=-mu[i];
}
}
}
void Prepare()
{
for (int i=2;i<=M;i++)
{
int x=i;
for (int j=1;j<=sqrt(i);j++)
if (x%j==0)
{
c[i].pb(j);
if (x/j!=j)
c[i].pb(x/j);
}
}
for (int i=1;i<=M;i++)
for (int j=0;j<c[i].size();j++)
(f[i]+=mu[i/c[i][j]]*c[i][j]*(c[i][j]-1))%=mod;
}
int main()
{
Getmobius();
Prepare();
while (scanf("%d",&n)!=EOF)
{
for (int i=1;i<=M;i++)
cnt[i]=0;
for (int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
for (int j=0;j<c[x].size();j++)
cnt[c[x][j]]++;
}
int ans=0;
for (int i=2;i<=M;i++)
(ans+=cnt[i]*cnt[i]%mod*f[i])%=mod;
printf("%d\n",(ans+mod)%mod);
}
return 0;
}
Lucky
Accepts: 34 Submissions: 267
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
问题描述
wld有n个数(a1…an)
保证对于任意1≤i≤n,1≤ai≤n
wld有一个常数k保证2≤k≤2∗n
为了消除歧义保证k为奇数
他有m个询问
每个询问有参数l1,r1,l2,r2
对于每个询问你需要回答有多少个二元组(i,j)满足:
l1≤i≤r1且l2≤j≤r2且ai+aj=k
保证1≤n≤30000,1≤m≤30000
输入描述
多组数据(最多5组)
对于每组数据:
第一行:一个数n表示数的个数
接下来一行:一个数k表示wld的常数
接下来一行:n个数,依次为a1,a2,…an
接下来一行:一个数m表示询问数
接下来m行:四个数l1,r1,l2,r2表示这组询问的参数
输出描述
对于每组数据:
对于每个询问输出二元组的数目
输入样例
5
3
1 2 1 2 3
1
1 2 3 5
输出样例
2
Hint
a1 + a4 = 3
a2 + a3 = 3
莫队或者分块都可以。
莫队:
(类似于容斥原理)
分块:
预处理出