您的位置:首页 > 其它

1439 互质对

2016-09-13 11:47 309 查看
1439 互质对

题目来源: CodeForces
基准时间限制:2 秒 空间限制:131072 KB

有n个数字,a[1],a[2],…,a
。有一个集合,刚开始集合为空。然后有一种操作每次向集合中加入一个数字或者删除一个数字。每次操作给出一个下标x(1 ≤ x ≤ n),如果a[x]已经在集合中,那么就删除a[x],否则就加入a[x]。

问每次操作之后集合中互质的数字有多少对。

注意,集合中可以有重复的数字,两个数字不同当且仅当他们的下标不同。

比如a[1]=a[2]=1。那么经过两次操作1,2之后,集合之后存在两个1,里面有一对互质。

Input
单组测试数据。
第一行包含两个整数n 和 q (1 ≤ n, q ≤ 2 × 10^5)。表示数字的种类和查询数目。
第二行有n个以空格分开的整数a[1],a[2],…,a
(1 ≤ a[i] ≤ 5 × 10^5),分别表示n个数字。
接下来q行,每行一个整数x(1 ≤ x ≤ n),表示每次操作的下标。

Output
对于每一个查询,输出当前集合中互质的数字有多少对。

Input示例
样例输入1
5 6
1 2 3 4 6
1
2
3
4
5
1
样例输入2
2 3
1 1
1
2
1

Output示例
样例输出1
0
1
3
5
6
2
样例输出2
0
1
0
思路:容斥原理;求容斥每个数与其他数不互质的对数,然后sum+总的再减去不互质的即可;


#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<stdlib.h>
#include<queue>
#include<string.h>
#include<set>
#include<map>
#include<math.h>
using namespace std;
typedef long long LL;
bool flag[600005];
LL cnt[600005];
int ff[600005];
bool prime[600005];
LL sum = 0;
int b[20];
int bns[600005];
int ans[600000];
int n;
void slove(int x,int v);
int main(void)
{
int q;
scanf("%d %d",&n,&q);
memset(cnt,0,sizeof(cnt));
memset(flag,0,sizeof(flag));
int i,j;int cn = 0;
for(i = 2; i < 1000; i++)
{
if(!prime[i])
{
for(j = i; ((LL)i*(LL)j) <= 500000; j++)
{
prime[i*j] = true;
}
}
}
for(i = 2;i < 500000; i++)
{
if(!prime[i])
{
ans[cn++] = i;
}
}
for(i = 0;i < cn ;i++)
{
for(j = 1;ans[i]*j <= 500000;j++)
{
ff[ans[i]*j] = ans[i];
}
}
for(i = 0; i < n; i++)
{
int x;
scanf("%d",&bns[i]);
}
n = 0;
while(q--)
{
int x;
scanf("%d",&x);
int id = x;
x = bns[x-1];
{
slove(x,id);
}
printf("%lld\n",sum);
}
return 0;
}
void slove(int x,int v)
{
int fl = 0;
if(flag[v])
{
flag[v]=false;
n--;
sum-=n;
fl = 1;
}
else
{
flag[v]=true;
sum += n;
n++;
}//printf("%d\n",sum);
int c = x;
int cn = 0;
while(c>1)
{
if(cn==0)
{
b[cn++] = ff[c];
}
else if(b[cn-1]!=ff[c])
{
b[cn++] = ff[c];
}
c/=ff[c];
}
if(fl)
{
int i ,j;
for(i = 1; i < (1<<cn); i++)
{
int ac = 1;
int t = 0;
for(j = 0; j < cn; j++)
{
if(i&(1<<j))
{
t++;
ac*=b[j];
}
}
if(t%2)
{
cnt[ac]--;
sum += cnt[ac];
}
else
{
cnt[ac]--;
sum -= cnt[ac];
}
}
}
else
{
int i ,j;
for(i = 1; i < (1<<cn); i++)
{
int ac = 1;
int t = 0;
for(j = 0; j < cn; j++)
{
if(i&(1<<j))
{
t++;
ac*=b[j];
}
}
if(t%2)
{
sum -= cnt[ac];
cnt[ac]++;
}
else
{
sum += cnt[ac];
cnt[ac]++;
}
}
}
}



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: