51nod 1439 互質對
阿新 • • 發佈:2018-12-10
題目連結
題意:
給 個數,然後 次詢問,每次詢問一個 ,如果這個 沒有出現過,就在集合中新增一個 ,如果出現過就把 刪去,換句話說,就是每個下標只能選或者不選,但是裡面的數重複不重複無所謂,然後每次操作完詢問集合裡面互質的對數有多少種
思路:
我看的這個部落格是計算每次加進去或取出來的這個數,與當前集合互質的對數 但是怎麼求喃?這個是個關鍵: 根據部落格的意思:add=含有因子1的個數+含有因子2的個數+含有因子3的個數+含有因子4的個數+…+… 也就是說假如這個數 含有因子 …. add=+含有因子 的個數+含有因子 的個數+含有因子 的個數+含有因子 的個數
然後我還學到了一個 篩出每個數所有的因子的方法,嘿嘿嘿~
#include"bits/stdc++.h"
using namespace std;
typedef long long LL;
const int maxn=5e5+5;
const int MOD=1e9+7;
int Fac[maxn],a[maxn];//Fac[i]表示i這個因子有多少個
vector<int>prime,factor[maxn];
bool vis[maxn];
int mu[maxn];
void PHI(int n)
{
memset(vis,1,sizeof(vis));
mu[1]=1;
for(LL i=1;i<=n;i++)
{
for(LL j=1;i*j<=n;j++)//篩因子
{
factor[i*j].push_back(j);
}
if (i==1)continue;//篩質數要從2開始
if(vis[i])
{
prime.push_back(i);
mu[i]=-1;
}
for(LL j=0;j<prime.size()&&i*prime[j]<=n;j++)
{
vis[i*prime[j]]=0;
if(i%prime[j]==0)
{
mu[i*prime[j]]=0;
break;
}
else mu[i*prime[j]]=-mu[i];
}
}
}
bool has[maxn];//來看下標為i的出現過沒得
int main()
{
PHI(maxn-5);
int N,M;
while(cin>>N>>M)
{
memset(Fac,0,sizeof Fac);
memset(has,0,sizeof has);
LL ans=0;
for(int i=1;i<=N;i++)scanf("%d",a+i);
while(M--)
{
int id,t;
scanf("%d",&id);
t=a[id];
int d;
if(has[id])
{
for(int j=0;j<factor[t].size();j++)d=factor[t][j],Fac[d]--;
for(int j=0;j<factor[t].size();j++)d=factor[t][j],ans-=mu[d]*Fac[d];
}
else
{
for(int j=0;j<factor[t].size();j++)d=factor[t][j],ans+=mu[d]*Fac[d];
for(int j=0;j<factor[t].size();j++)d=factor[t][j],Fac[d]++;
}
has[id]^=1;
cout<<ans<<endl;
}
}
}