poj1091 跳蚤 容斥原理

2022-05-12 21:26:29 字數 1399 閱讀 9620

思路:假設跳蚤選擇x1個第一張卡片,x2個第二張卡片。。。xn個第n張卡片,xn+1張寫著m的卡片,那麼就可以列出方程:a1*x1+a2*x2+…+an*xn+m*x(n+1)=1

由於可以向左跳和向右跳,因此題目即問上述不定方程是否有解?答案以及它的證明可以在任何一本數論書中找到,它的充要條件是(a1,a2,a3。。。an,m)|1 即a1,a2,a3。。。an,m互質,這樣題目就成為:有n+1個正整數,其中最大的數為m,問所有符合條件的序列中有多少是互質的。

組合數學很多都是正難則反易的,考慮問題的背面有多少最大公約數不為1的?先把m分解質因數,m的每乙個因子可以看成乙個集合,集合中的元素為最大公約數為這個因子的序列,這個問題的答案便是所有集合的並中集合的元素,用容斥就顯然了

最後將總數m^n減去最大公約數不為1的個數,結果就是互質的個數了

順便吐槽下,雖然容斥屬於集合論裡面的東西,但經常用來證明數論題目,最早學它好像就是用來推導尤拉函式的公式時用的

#include

#include

#include

#include

#define ll __int64

using namespace std;

llfactor[100000],h=0,stack[100000],top=0,mt,nt,ret1;

ll quickpow(ll n,ll m)

ll ret=1;

while (m)

if ((m & 1))ret*=n;

n*=n;

m>>=1;

return ret;

void dfs(ll step,ll now,ll layer,ll num)

if (step==layer)

for(inti=now+1;i<=h-layer+step+1;i++)dfs(step+1,now+1,layer,num*factor[i]);

int main()

ll n;

scanf("%i64d%i64d",&nt,&mt);

n=mt;

while ((n & 1)==0)

ll q=sqrt(n);

for(ll i=3;i<=q && n!=1;i+=2)

if (n % i==0)factor[++h]=i;

while(n%i==0)n=n/i;

if (n!=1)factor[++h]=n;

ll ans=0,flag=-1;

for(ll i=1;i<=h;i++)

flag*=-1;

top=ret1=0;

dfs(0,0,i,1);

ans+=ret1*flag;

printf("%i64d\n",(ll)quickpow(mt,nt)-ans);

return 0;

跳蚤 POJ 1091 容斥原理

跳蚤time limit 1000ms memory limit 10000k total submissions 8723 accepted 2601 description z城市居住著很多只跳蚤。在z城市週六生活頻道有乙個娛樂節目。乙隻跳蚤將被請上乙個高空鋼絲的正 鋼絲很長,可以看作是無限長。...

POJ1091 跳蚤 容斥

解題報告 設數字分別為a1 a2,a3 m 那麼若方程x1 a1 x 2a2 xn 1m 1有解 則這張卡片可行。而此方程有解的充要條件為gc d a1 a2,a3 m 1 所以本題即為求gc d a1 a2,a3 m 1 1 a 1,a2 a3 an m 的方案數。那麼可以反著求gc d a1 a...

POJ 1091 跳蚤 容斥原理 數論

題目大意 中文題意,不多贅述 題目分析 根據題目的意思,其實只需要讓所有數的最大公約數為1就可以滿足條件,好像是用到了歐幾里得的一些知識,奈何我的數論比較菜,也不會證明,就直接用網上大牛們的結論吧,題目說了第n 1個數已經幫我們選好了,為m,所以我們只需要找出有多少種情況選擇n個與m互質的數就是題目...