Given you a sequence of number a 1, a 2, …, a n, which is a permutation of 1…n.
You need to answer some queries, each with the following format:
Give you two numbers L, R, you should calculate sum of gcd(a[i], a[j]) for every L <= i < j <= R.
Input
First line contains a number T(T <= 10),denote the number of test cases.
Then follow T test cases.
For each test cases,the first line contains a number n(1<=n<= 20000).
The second line contains n number a 1,a 2,…,a n.
The third line contains a number Q(1<=Q<=20000) denoting the number of queries.
Then Q lines follows,each lines contains two integer L,R(1<=L<=R<=n),denote a query.
Output
For each case, first you should print “Case #x:”, where x indicates the case number between 1 and T.
Then for each query print the answer in one line.
Sample Input
1
5
3 2 5 4 1
3
1 5
2 4
3 3
Sample Output
Case #1:
11
4
0
把自己蠢哭了,智障去每次去dfs一个数的因子,直接预处理存起来不就好了嘛,预处理第一个询问居然直接去暴力,对自己无语啊。。。
优化版:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<bitset>
#include<vector>
#define N 20500
#define INF 10000000000
#define mod 1000000007
using namespace std;
typedef long long ll;
vector<int> factor[20005];
int phi[N];
void init()
{
for(int i=0;i<N;i++)
phi[i]=i;
for(int i=2;i<N;i++)
{
if(phi[i]==i)
{
for(int j=i;j<N;j+=i)
phi[j]-=phi[j]/i;
}
}
for(int i=1;i<=20000;i++)
for(int j=i;j<=20000;j+=i)
factor[j].push_back(i);
}
int block[N];
struct node
{
int l,r;
int index;
}query[N];
ll ans[N];
int a[N];
int cmp(node x1,node x2)
{
if(block[x1.l]==block[x2.l])
return x1.r<x2.r;
return block[x1.l]<block[x2.l];
}
int cnt[N];
int curL,curR;
ll curAns;
void add(int x)
{
for(int i=0;i<factor[x].size();i++)
{
int num=factor[x][i];
curAns+=phi[num]*cnt[num];
cnt[num]++;
}
}
void sub(int x)
{
for(int i=0;i<factor[x].size();i++)
{
int num=factor[x][i];
cnt[num]--;
curAns-=phi[num]*cnt[num];
}
}
void work(int L,int R)
{
while(curL<L)
{
sub(a[curL]);
curL++;
}
while(curL>L)
{
curL--;
add(a[curL]);
}
while(curR>R)
{
sub(a[curR]);
curR--;
}
while(curR<R)
{
curR++;
add(a[curR]);
}
}
int main()
{
init();
int t,n;
scanf("%d",&t);
int cal=1;
while(t--)
{
memset(cnt,0,sizeof(cnt));
scanf("%d",&n);
int limit=(int)sqrt(n);
for(int i=1;i<=n;i++)
block[i]=(i-1)/limit;
for(int i=1;i<=n;i++)
scanf("%d",a+i);
int m;
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&query[i].l,&query[i].r);
query[i].index=i;
}
sort(query+1,query+1+m,cmp);
curAns=0;
for(int i=query[1].l;i<=query[1].r;i++)
add(a[i]);
ans[query[1].index]=curAns;
curL=query[1].l;
curR=query[1].r;
for(int i=2;i<=m;i++)
{
work(query[i].l,query[i].r);
ans[query[i].index]=curAns;
}
printf("Case #%d:\n",cal++);
for(int i=1;i<=m;i++)
printf("%lld\n",ans[i]);
}
return 0;
}
智障的版本:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<bitset>
#include<vector>
#define N 20500
#define INF 10000000000
#define mod 1000000007
using namespace std;
typedef long long ll;
vector<int> prime;
int phi[N];
void init()
{
for(int i=0;i<N;i++)
phi[i]=i;
for(int i=2;i<N;i++)
{
if(phi[i]==i)
{
prime.push_back(i);
for(int j=i;j<N;j+=i)
phi[j]-=phi[j]/i;
}
}
}
int block[N];
struct node
{
int l,r;
int index;
}query[N];
int ans[N];
int a[N];
int cmp(node x1,node x2)
{
if(block[x1.l]==block[x2.l])
return x1.r<x2.r;
return block[x1.l]<block[x2.l];
}
int gcd(int a,int b)
{
return a%b==0?b:gcd(b,a%b);
}
int cnt[N];
int curAns,curL,curR;
int fac[100];
int e[100];
int k;
void getFac(int x)
{
k=0;
for(int i=0;prime[i]*prime[i]<=x;i++)
{
if(x%prime[i]==0)
{
fac[k]=prime[i];
e[k]=0;
while(x%prime[i]==0)
{
x/=prime[i];
e[k]++;
}
k++;
}
}
if(x>1)
{
fac[k]=x;
e[k]=1;
k++;
}
}
int state;
void dfs(int cur,int temp)
{
if(cur==k)
{
//cout<<temp<<endl;
if(state==0)
{
cnt[temp]--;
curAns-=phi[temp]*cnt[temp];
}
else
{
curAns+=phi[temp]*cnt[temp];
cnt[temp]++;
}
return ;
}
dfs(cur+1,temp);
int c=temp;
for(int i=1;i<=e[cur];i++)
{
c*=fac[cur];
dfs(cur+1,c);
}
}
void dfs2(int cur,int temp)
{
if(cur==k)
{
cnt[temp]++;
return ;
}
dfs2(cur+1,temp);
int c=temp;
for(int i=1;i<=e[cur];i++)
{
c*=fac[cur];
dfs2(cur+1,c);
}
}
void work(int L,int R)
{
while(curL<L)
{
state=0;
getFac(a[curL]);
dfs(0,1);
curL++;
}
while(curL>L)
{
state=1;
curL--;
getFac(a[curL]);
dfs(0,1);
}
while(curR>R)
{
state=0;
getFac(a[curR]);
dfs(0,1);
curR--;
}
while(curR<R)
{
state=1;
curR++;
getFac(a[curR]);
dfs(0,1);
}
}
int main()
{
init();
int t,n;
scanf("%d",&t);
int cal=1;
while(t--)
{
memset(cnt,0,sizeof(cnt));
scanf("%d",&n);
int limit=(int)sqrt(n);
for(int i=1;i<=n;i++)
block[i]=(i-1)/limit;
for(int i=1;i<=n;i++)
scanf("%d",a+i);
int m;
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&query[i].l,&query[i].r);
query[i].index=i;
}
sort(query+1,query+1+m,cmp);
curAns=0;
for(int i=query[1].l;i<=query[1].r;i++)
{
getFac(a[i]);
dfs2(0,1);
for(int j=i+1;j<=query[1].r;j++)
curAns+=gcd(a[i],a[j]);
}
ans[query[1].index]=curAns;
curL=query[1].l;
curR=query[1].r;
for(int i=2;i<=m;i++)
{
work(query[i].l,query[i].r);
//cout<<curL<<" "<<curR<<endl;
/*for(int i=1;i<=5;i++)
cout<<cnt[i]<<" ";
cout<<endl;*/
ans[query[i].index]=curAns;
}
printf("Case #%d:\n",cal++);
for(int i=1;i<=m;i++)
printf("%d\n",ans[i]);
}
return 0;
}