[成都七中]GCD

给一个1-N的排列a,Q组询问(l,r) sigma(gcd(a[i],a[j])),i=l..r,j=i+1..r

N,Q<=10^4,3s,64M

出处:http://cdqz.openjudge.cn/2015/1050/

 

感觉题目确实不错。

虽然不知道标准解法是啥,但总算过了。

我们可以先对询问按r排序。

然后问题就是加一个数,询问两两gcd的后缀和这样一个东西。

我们考虑暴力做。那么就是O(N^2*gcd)。不能过。

如果不卡空间的话,前面筛法预处理一下数对应该就行了。

我们考虑一个东西:sigma(d=1..n,i,j=1..n/d,d*e((i,j)))=>sigma(d=1..n,d2=1..n/d,i,j=1..n/d/d2,u(d)*d2) (A)

u(d)*d2是要加到(i*d*d2,j*d*d2)这里的,然后现在是我们已知i*d*d2,枚举出所有的j*d*d2,这个显然就是枚举约数(前面预处理约数和u函数)。

所有复杂度就是上面(A)式的答案。

 

 

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<set>
 5 #include<vector>
 6 #include<map>
 7 #include<queue>
 8 #include<string>
 9 #include<bitset>
10 #include<iomanip>
11 #include<iostream>
12 #include<cmath>
13 using namespace std;
14 
15 #define rep(i,x,y) for(i=x;i<=y;i++)
16 #define _rep(i,x,y) for(i=x;i>=y;i--)
17 #define CL(S,x) memset(S,x,sizeof(S))
18 #define CP(S1,S2) memcpy(S1,S2,sizeof(S2))
19 #define ALL(x,S) for(x=S.begin();x!=S.end();x++)
20 #define sqr(x) ((x)*(x))
21 #define mp make_pair
22 #define fi first
23 #define se second
24 #define upmin(x,y) x=min(x,y)
25 #define upmax(x,y) x=max(x,y)
26 #define pb push_back
27 #define COUT(S,x) cout<<fixed<<setprecision(x)<<S<<endl
28 #define A fi.fi
29 #define B fi.se
30 #define pos se
31 
32 typedef long long ll;
33 typedef long double ld;
34 typedef pair<pair<int,int>,int> pii;
35 
36 template<class T> inline void read(T&x){bool fu=0;char c;for(c=getchar();c<=32;c=getchar());if(c=='-')fu=1,c=getchar();for(x=0;c>32;c=getchar())x=x*10+c-'0';if(fu)x=-x;};
37 template<class T> inline void read(T&x,T&y){read(x);read(y);}
38 template<class T> inline void read(T&x,T&y,T&z){read(x);read(y);read(z);}
39 inline char getc(){char c;for(c=getchar();c<=32;c=getchar());return c;}
40 
41 int n,q,i,j,k,l,r,p,v,d,d2,de,res,u[10010],a[10010],s[10010],ss[10010],home[10010];
42 
43 int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
44 pii c[10010];int ans[10010];
45 bool cmp(pii a,pii b){return a.B<b.B;}
46 
47 int edge,e[100010],b[100010],fir[10010];
48 void add(int x,int y){e[++edge]=y;b[edge]=fir[x];fir[x]=edge;}
49 
50 int main()
51 {
52     //freopen("1.in","r",stdin);freopen("1.out","w",stdout);
53     
54     read(n);rep(i,1,n)read(a[i]),home[a[i]]=i;
55     read(q);rep(i,1,q)read(c[i].A),read(c[i].B),c[i].pos=i;
56     sort(c+1,c+1+q,cmp);
57     
58     rep(i,1,n)
59     {
60         u[i]=1;
61         for(p=i,d=2;d*d<=p;d++)
62         if(p%d==0){u[i]=-u[i];p/=d;if(p%d==0){u[i]=0;break;}}
63         if(p>1)u[i]=-u[i];
64     }
65     rep(i,1,n)for(j=i;j<=n;j+=i)add(j,i);
66     
67     //double ti=clock();
68     v=1;
69     rep(r,1,n)
70     {
71         res=0;
72         for(j=fir[a[r]];j;j=b[j])
73         {
74             int d=e[j];
75             if(u[d])
76             for(k=fir[a[r]/d];k;k=b[k])
77             {
78                 d2=e[k];de=d*d2;
79                 for(p=de;p<=n;p+=de)
80                 if(home[p]<r)s[home[p]]+=u[d]*d2;
81             }
82         }
83         ss[r]=0;_rep(i,r-1,1)ss[i]=ss[i+1]+s[i];
84         for(;v<=q&&c[v].B==r;v++)ans[c[v].pos]=ss[c[v].A];
85     }
86     //printf("%lf\n",clock()-ti);while(1);
87     rep(i,1,q)printf("%d\n",ans[i]);
88     
89     scanf("\n");
90     return 0;
91 }
View Code

 

posted @ 2014-04-13 10:56  FancyCoder0  阅读(684)  评论(0编辑  收藏  举报