[成都七中]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 }