1. 程式人生 > >51nod 1439:互質對 容斥原理 深搜!!!

51nod 1439:互質對 容斥原理 深搜!!!

 收藏  取消關注

有n個數字,a[1],a[2],…,a[n]。有一個集合,剛開始集合為空。然後有一種操作每次向集合中加入一個數字或者刪除一個數字。每次操作給出一個下標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[n] (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

如果已知當前集合中互質的個數為ans,那麼加入或者刪除某個元素最後的結果也就是ans加上或減去該元素與集合中元素互質的個數。

所以要求的就是一個數與集合中各個數之間互質的個數。

做法是把每一個數拆成各個質數因子的乘積,然後對這些質數進行排列組合,那6來說,先假設將所有元素都是與6互質的,然後這裡面減去因子有2的(與6一定不互質了),再減去因子有3的,但是這裡面減的話,有部分減重複了,就是因子既有2又有3的,所以又要加上因子6的個數,使用容斥原理最終得到結果。

程式碼:

#include <iostream>  
#include <algorithm>  
#include <cmath>  
#include <vector>  
#include <string>  
#include <cstring>  
#pragma warning(disable:4996)  
using namespace std;

#define maxn 500005
vector<int>prime[maxn];
int cnt[maxn], v[maxn], a[maxn], flag[maxn];
int x;
int n, q;
long long ans;

void dfs(int num,int mul,int symbol,int add_minus)
{
	if (num == prime[x].size())
	{
		if (add_minus == -1)
			cnt[mul]--;
		
		ans += symbol*cnt[mul];

		if (add_minus == 1)
			cnt[mul]++;

		return;
	}
	dfs(num + 1, mul, symbol, add_minus);
	dfs(num + 1, mul*prime[x][num], -symbol, add_minus);
}
int main()
{
	//freopen("i.txt", "r", stdin);
	//freopen("o.txt", "w", stdout);

	int i, j;
	for (i = 2; i < maxn; i++)
	{
		if (v[i])continue;
		for (j = i; j < maxn; j = j + i)
		{
			v[j] = 1;
			prime[j].push_back(i);
		}
	}
	cin>>n>>q;
	for (i = 1; i <= n; i++)
	{
		cin>>a[i];
	}
	ans = 0;
	for (i = 1; i <= q; i++)
	{
		cin>>x;
		if (flag[x] == 0)
		{
			flag[x] = 1;
			x = a[x];
			dfs(0, 1, 1, 1);
		}
		else
		{
			flag[x] = 0;
			x = a[x];
			dfs(0, 1, -1, -1);
		}
		cout<<ans<<endl;
	}
	//system("pause");
	return 0;
}


相關推薦

51nod 1439 原理

 收藏  取消關注 有n個數字,a[1],a[2],…,a[n]。有一個集合,剛開始集合為空。然後有一種操作每次向集合中加入一個數字或者刪除一個數字。每次操作給出一個下標x(

hdu 4135 a到b的範圍中多少數與n

namespace rim 所有 += ont put contain 質因數 tor Co-prime 題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=4135 input

[洛谷P5106]dkw的lcm尤拉函式+原理+擴充套件尤拉定理

分析 考慮使用尤拉函式的計算公式化簡原式,因為有: \[lcm(i_1,i_2,...,i_k)=p_1^{q_{1\ max}} \times p_2^{q_{2\ max}} \times ... \times p_m^{q_{m\ max}}\] 其實就是分解質因數,丟到那個尤拉函式計算式子裡:

素,原理,HDU4135 POJ2407 HDU1796

(三道題目的完整程式碼在文章最後) 這幾道題都是有關互素和容斥原理的問題, 要求1~n 中與 m互質的自然數的個數的基本思路是:先找到m的所有質因數然後用容斥原理找出在1~n的範圍內與m互質的數的個數。 以HDU4135(Coprime)為例。點選看原題 該題讓我們找出

51nod 1439

題目連結 題意: 思路: 題目連結 題意: 給 NN 個數,然後 QQ 次詢問,每次詢問一個 idid ,如果這個 idid 沒有出現過,就在集合中新增一個 a[id]a[id] ,如果出現過就把 a[id]a[id] 刪去,換句話

求N(10^14)以內與N的數的和(原理,或者尤拉函式)

#include <iostream> #include <cstring> #include <algorithm> #include <cmath>

原理 —— 求1~n有多少個數與k(二進位制演算法詳細解釋&模板)

這裡有一道經典的例題,可以看一下:點選開啟連結 這裡的n可能要大於k的,所以不能用尤拉函式去做。 我們首先把k分解質因數,儲存到p陣列中,num表示質因子的數量。 void pr(int k) //求k的質因子 { num = 0; for (int i = 2 ;

原理-求區間內與n的數】HDOJ Co-prime 4135

Given a number N, you are asked to count the number of integers between A and B inclusive which are relatively prime to N. Two integers are said to be co-

求1~n與x的數的個數(6個題、原理

HDU 4135、POJ 2773、HDU 1695、HDU 2841、ZOJ 2836、HDU 1796 HDU 4135 Co-prime 題意: 求[l,r]與x互質的數的

原理求1到n與k個數

參考部落格:傳送門 此處的k<=1e9、 #include<cmath> #include<cstring> #include<cstdio> #include<algorithm> #include<vecto

求1~n中與m的數的個數(m>n) 附hdu1695題解(尤拉函式+原理)

int calc(int n,int m) { //求1~n 與m互質的數的個數 int num=getFactors(m); //先將m分解質因數 int sum=0; //先求出不互質的個數,最後用n減去該數 for(int state=1;

51nod 1284 2 3 5 7的倍數 | 原理

using targe pre include mage style 部分 pan 相交 用容斥原理求出不滿足條件的個數cnt,然後用n-cnt就得到答案了。 這裏不滿條件的數就是能整除2,3,5,7這些數的集合並集。要計算幾個集合並集的大小,我們要先將所有單

「2017 山東一輪集訓 Day7」逆序 - - 分塊揹包

我不會整數劃分 考慮dp,轉移方程形如 f ( i

5297 十分優(lie)

如果做過簡化版,看到這道題第一反應就是二分答案,找最小的N滿足他前面的數(包含他自己)刪去可以開1到r次方的數之後只剩下n個。但是這道題用二分答案會TLE(不知道寫的好會不會,但是我會)。且找N他前面的數(包含他自己)刪去可以開1到r次方的數之後剩下多少個的方法也很重

組合數學原理及其應用

容斥原理 例題:從1到1000中不能被5,6,8整除的整數個數。 令P1具有被5整除的性質,P2具有被6整除的性質,P3被8整除性質。 S是前1000個正整數的集合希望求出三個性質同時不滿足的個數 |A1| = floor(1000/5) = 200;|A2| =

原理的(二進位制思想和因子分解+模板)

#include<iostream> #include<string> #include<cstdio> #include<algorithm> #include<cmath> #include<iomanip

51nod 1407 與與與與 dp+原理

題意 有n個整數,問從他們中取出若干個數字相與之後結果是0的有多少組。 答案比較大,輸出對於 1,000,000,007 (1e9+7)取模後的結果。 1<=n<=1,000,000,

區間素(篩法尤拉函式模板+原理)(1695)

GCD Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 8818    Accepted Submission

求a~b內與n素的數的個數 原理

題意:給定你一個數n,請你統計出在[a,b]這個區間中和n互質的數的個數。兩個數互質當且僅當他們除了1之外沒有其他的公共因子或者他們最大的公共因子是1。1和任何數是互素的。 輸入:第一行輸入一個整

離散數學原理

這題答案有點問題,並不能滿分通過,想滿分的移步吧,只提供一個思路,思路是沒問題的 提示:求兩個整數a, b的最小公倍數lcm(a,b),可以利用a, b的最大公約數gcd(a,b)來完成,即lcm(a, b) = a*b/gcd(a, b) gcd可以這