思路:假設跳蚤選擇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互質的數就是題目...