可以得到這樣的關係:奇數加、偶數減
題目大意
給一串數字,求解互質四元組的個數(注意不必兩兩互質)
解題思路
網上有很多**,但是詳細講解的很少,這裡結合筆者的思路詳細論述一下解題思路,耐心一看。
首先容易想到,想計算不互質的四元組的個數,再用總的減去,關鍵是怎樣計數不互質四元組的個數??
列舉公約數,對於同乙個四元組(6,12,18,36)可能既有公約數2,也有公約數3,和公約數6,我們在列舉過程中是計數到2?3?還是6?
容斥啊!!公約數有奇數個素因子就+,偶數個素因子就-(2、3都含有乙個素因子就加,6含有2、3兩個素因子就減);找到公約數就要對讀入的每乙個資料進行素因子分解,對素因子進行組合,記錄組合得到因子k含有幾個素因子,用num[k]表示;開乙個全域性陣列cnt[k]計數含有因子k的資料個數。然後根據容斥定理,如果因子k含有偶數個素因子(如6=2×3)減,奇數個素因子(如2=2,5=5,30=2×3×5)加,累加起來就得到不互質四元組的總個數啦!
有幾個關鍵點
key 1:理解cnt[i]表示含有因子i的資料的個數(2,4,6,8,10這組資料中cnt[i]=5)
num[i]表示因子i含有的不同素因子的個數(num[6]=2,減)
key 2:怎樣得到cnt[i]、num[i],或者說怎樣實現素因子組合?用到了二進位制表示的思想,第j位的1表示第j個素因子參與累乘,0表示不參與累乘,比如含有素因子2*3*5*7,1010表示2*1*5*1,0001表示1*1*1*7,以此類推……這樣,只要素因子分解完記錄含有素因子的個數tol,那麼就有tol位二進位制,注意到2*3*5*7*11*13>10000,所有最多有6位二進位制;對於任意乙個範圍內的數i,遍歷所有位j(從低位到高位),i&(1《j)==1,表示i的第j位二進位制為1,意思是第j個素因子參與累乘;依據這樣的意義,遍歷二進位制範圍內的所有數i和i對應的所有二進位制數字j,更新陣列cnt[k]和num[k]即可!!
key 3:筆者錯誤的理解了素因子組合不是整數分解得到所有約數,得到了錯誤的num[i]和cnt[i],舉個例子:2,4,8,16,32這組資料,對應的
cnt = 5 , 4 , 3 , 2 , 1
num = 1 , 1 , 1 , 1 , 1
本來不可能有互質四元組的,但在容斥的時候會把cnt[2]、cnt[4]都算進去,原因就在於我進行了約數分解,並不是素因子組合!!!
正確答案是
cnt = 5 , 0 , 0 , 0 , 0
num = 1 , 0 , 0 , 0 , 0 (因為只有乙個素因子2無法組合出4,8,16,32)
好了,參考著**理解一下唄!
#include#include#include
using
namespace
std;
const
int maxn=10000+10
;typedef
long
long
ll;ll p[maxn];
intprime[maxn],cnt[maxn],num[maxn];
void divide(int
n)while(n%i==0
); }
}if(n>1) prime[tot++]=n;
for (int i=1;i<(1
<)
}cnt[k]++;
num[k]=sum;
}}int
main()
ll ans=0
;
for (int i=2;i)
}printf(
"%lld\n
",p[n]-ans);
}return0;
}
poj 3904 容斥原理 質因數分解
題意 給你一串數字,問選擇4個數且這四個數的最大公因數為1的選法為多少種 解法 很容易想到容斥原理,答案為選擇四個數的所有種數 四個數存在最大公因數為質數 四個數存在最大公因數為兩個質數之積 四個數存在最大公因數為三個質數之積。就是處理各個由質因子相乘得到的因子的數量比較麻煩。首先,題目給的資料範圍...
POJ 3904 Sky Code 容斥原理
題意 選出最大公約數為1的四元組的方案 思路 容斥原理 總的方案c n,4 減去t 1 t 2 t 3 kt k t i 表示四元組質因子的個數為i的方案數 include include include using namespace std const int maxn 10010 typede...
POJ3904 Sky Code 容斥原理
這道題很容易想到用總的情況減去不互素的情況,需要統計不同素因子對應的資料個數,但這樣會多算 比如2的因子減過一次,3的因子減過一次,這時6的情況 eg 6,12,18,24 就多減了一次 因此想到用容斥原理。問題的關鍵在於,怎麼得到不同素因子組合對應的情況。附上大佬部落格orz 這篇部落格講的很清楚...