C 演算法提高 翔集合

2021-10-23 13:08:49 字數 2006 閱讀 9999

題目閱覽

集合m至少有兩個元素(實數),且m中任意兩個元素差的絕對值都大於2,則稱m為「翔集合」,已知集合s=,請求出n的子集中共有多少個翔集合。

輸入格式:輸入共一行,乙個整數n.(n>=2)

輸出格式:輸出共一行,乙個整數表示s的子集中共有多少個翔集合,由於個數可能過大,請輸出這個值除以1000007的餘數。

樣例輸入1

4樣例輸出1

1題目簡介

我想以從數字1到10開始依次的翔集合來介紹,如下圖所示:

以上是1到10以內所有翔集合的個數,滿足任意兩個元素差的絕對值都大於2,其中f(n)表示包含n的翔集合的個數,f(n-1)表示不包含n的所有翔集合的個數,最終結果就是將兩者相加,然後再加上兩個元素的集合,對於n來說,也就是n-3,便得出了最終的通項公式:

f(n)=f(n-1)+f(n-3)+n-3 (f(3)=f(2)=0,f(4)=1)

觀察上述通項公式:右邊有三個變數f(n-1)、f(n-3)、n-3,但f(n-1)和f(n-3)不連續,所以需要補個f(n-2),更加方便矩陣計算,從而我們可以建立乙個1*5的矩陣an=|f(n-1) f(n-2) f(n-3) n-3 1|,與此同時需要乙個轉移矩陣b使得an×b=|f(n) f(n-1) f(n-2) n-2 1|=an+1等式成立,又因為an=a4bn-4,而a4=|f(4) f(3) f(2) 2 1|=|1 0 0 2 1|,所以只要求得bn-4就可對矩陣b求快速冪,計算得出矩陣b如下:

思路簡介

根據上述得出的通項公式,通過數學轉換建立轉移變換矩陣快速冪,有關矩陣快速冪計算參照:矩陣快速冪

具體演算法思想:首先,根據輸入得到需要計算的n值,然後通過上述計算得出的b矩陣進行矩陣快速冪乘法得出結果,再乘以相對應的a矩陣,最後按照要求對1000007取餘輸出最後的結果。

翔集合實現**

#include #define mod 1000007

typedef long long ll;

typedef struct ma mat;// 用結構體代替陣列方便寫函式

mat e = , b = ;// e為單位矩陣、b為轉移矩陣

mat sq(mat a, mat b)

} }return c;

}mat qpow(mat a, ll n)

} return temp;// 返回矩陣a的n次方即矩陣temp

}int main()

b.m[0][0] = b.m[0][1] = b.m[1][2] = b.m[2][0] = b.m[3][0] = b.m[3][3] = b.m[4][3] = b.m[4][4] = 1;

int i, j;

for(i = 0;i < 5; ++i)

mat ans = qpow(b, n-4);

ll res = (ans.m[0][0]+2*ans.m[3][0]+ans.m[4][0])%mod;// 矩陣a=和res的第一列相乘在取餘即可

printf("%lld", res);

return 0;

}

執行截圖

注:以上方法參考這位博主的部落格:c語言實現 藍橋杯 演算法提高 翔集合

試題 演算法提高 翔集合

問題描述 集合m至少有兩個元素 實數 且m中任意兩個元素差的絕對值都大於2,則稱m為 翔集合 已知集合s 請求出n的子集中共有多少個翔集合。輸入格式 輸入共一行,乙個整數n.n 2 輸出格式 輸出共一行,乙個整數表示s的子集中共有多少個翔集合,由於個數可能過大,請輸出這個值除以1000007的餘數。...

C 常用集合演算法

set intersection 求兩個容器的交集 set union 求兩個容器的並集 set difference 求兩個容器的差集 1 set intersection 求交集,求交集的兩個集合必須有序,目標容器開闢空間需要從兩個容器中去最小值,set intersection返回值即是交集中...

c 常用集合演算法

演算法簡介 set intersection 求兩個容器的交集 set union 求兩個容器的並集 set difference 求兩個容器的差集 set intersection 功能描述 求兩個容器的交集 函式原型 set intersection iterator beg1,iterator...