題面不給……題意:動態增減集合中元素個數,動態求$gcd(i,j)==1$的數的個數。ios
坦白地講題解並沒徹底看懂……因而聽$lc$開了一會車(快開完時$xyz$強行砸場致使爛尾),結合着本身理解又推一遍想明白了……ide
在本題之中,咱們設$f(x)$爲$gcd(i,j)==x$的數的個數,$g(x)$爲$gcd(i,j)==kx$的數的個數。很顯然$f(x)=g(x)-f(2x)-f(3x)...$,這樣推下去,咱們就會發現這個係數實際上是符合莫比烏斯函數的,最後大力化簡就是:函數
\[ \sum_{d}^{} {μ(d)*g(d)} =f(d)\]。spa
如今定義$s(i)$爲當前選中的集合中爲$i$倍數數的個數,能夠看出,$g(i)=s(i)*(s(i)-1)/2$。3d
而後咱們就能夠預處理莫比烏斯函數,在每一次修改元素個數時候動態維護$s(i)$。code
可是咱們暴力求$ans$顯然會$T$……因而考慮每一次加入或刪除元素對於最後結果貢獻。blog
當咱們插入一個元素,對於每個能夠整除它的$i$,$Δans=μ(i)*((s(i)+1)*s(i)-s(i)*(s(i)-1))/2=μ(i)s(i)$。同理,刪除時,對於每個這樣的$i$,$Δans=μ(i)*((s(i)-2)*(s(i)-1)-s(i)*(s(i)-1))/2=-μ(i)(s(i)-1)$。而後咱們根據這個規律轉移便可。string
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 const int maxn=200005,maxx=500005; 7 bool notprime[maxx];int prime[maxx],cnt,mu[maxx]; 8 void init() 9 { 10 mu[1]=1; 11 for(int i=2;i<=500000;i++) 12 { 13 if(!notprime[i])prime[++cnt]=i,mu[i]=-1; 14 for(int j=1;j<=cnt&&i*prime[j]<=500000;j++) 15 { 16 notprime[i*prime[j]]=1; 17 if(i%prime[j])mu[i*prime[j]]=-mu[i]; 18 else {mu[i*prime[j]]=0;break;} 19 } 20 } 21 } 22 int n,m,a[maxn],s[maxx],maxv,t[maxn]; 23 int haha() 24 { 25 scanf("%d%d",&n,&m);init(); 26 for(int i=1;i<=n;i++)scanf("%d",&a[i]),maxv=max(maxv,a[i]); 27 long long ans=0; 28 for(int i=1;i<=m;i++) 29 { 30 int x;scanf("%d",&x);int sgn=t[x]?-1:1; 31 for(int j=1;j*j<=a[x];j++) 32 if(!(a[x]%j)) 33 { 34 if(sgn==1)ans+=1ll*mu[j]*s[j];else ans-=1ll*(s[j]-1)*mu[j];s[j]+=sgn*1; 35 if(j*j<a[x]) 36 { 37 if(sgn==1)ans+=1ll*mu[a[x]/j]*s[a[x]/j];else ans-=1ll*(s[a[x]/j]-1)*mu[a[x]/j]; 38 s[a[x]/j]+=sgn*1; 39 } 40 } 41 t[x]^=1; 42 printf("%lld\n",ans); 43 } 44 } 45 int sb=haha(); 46 int main(){;}