日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[CQOI]九连环(FFT优化+高精)

發布時間:2023/12/3 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [CQOI]九连环(FFT优化+高精) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 題目
  • 題解
  • code

題目

九連環是一種源于中國的傳統智力游戲。

如圖所示,九個的圓環套在一把“劍”上,并且互相牽連。游戲的目標是把九個圓環全部從“劍”上卸下。
圓環的裝卸需要遵守兩個規則
1.第一個(最右邊)環任何時候都可以任意裝上或卸下
2.如果第k個環沒有被卸下,且第k個環右邊的所有環都被卸下,則第k+l個環(第k個環左邊相鄰的環)
可以任意裝上或卸下與魔方的千變萬化不同,解九連環的最優策略是唯一的。
為簡單起見,我們以“四連環”為例,演示這一過程。這里用1表示環在“劍”上,0表示環已經卸下。
初始狀態為1111,每步的操作如下

  • 1101(根據規則2卸下第2個環)
  • 1100(根據規則1卸下第1個環)
  • 0100(根據規則2卸下第4個環)
  • 0101(根據規則1裝上第1個環)
  • 0111(根據規則2裝上第2個環)
  • 0110(根據規則1卸下第1個環)
  • 0010(根據規則2卸下第3個環)
  • 0001(根據規則1裝上第1個環)
  • 0001(根據規則2卸下第2個環)
  • 0000(根據規則1卸下第1個環)
  • 由此可見,卸下“四連環”至少需要10步。
    隨著環數增加,需要的步數也會隨之增多。例如卸下九連環.就至少需要341步。
    請你計算,有n個環的情況下,按照規則,全部卸下至少需要多少步

    Input
    輸入文件第一行,為一個整數m,表示測試點數目。
    接下來m行,每行一個整數n。
    1≤n≤10^5,1≤m≤10
    Output
    輸出文件共m行,對應每個測試點的計算結果

    Sample Input
    3
    3
    5
    9
    Sample Output
    5
    21
    341

    題解

    直接給遞推式f(n)=f(n?1)+2?f(n?2)+1f(n)=f(n-1)+2*f(n-2)+1f(n)=f(n?1)+2?f(n?2)+1,結論就是2n+13\frac{2^{n+1}}{3}32n+1?


    從三個不同的方向走向一起:
    1.1.1.買一本高中數學必修5,里面有九連環的結論詳細證明


    2.2.2.打表發現規律

    n1234567
    12510214285

    轉換成二進制,規律越發明顯

    n1234567
    12510214285
    1101011010101011010101010101

    好看吧!發現1,01,01,0是不相鄰的,就可以考慮二進制乘法,竹格利茲
    1010101×111010101101010111111111=(27+1?1)\begin{aligned} 1010101\\×11\\1010101\\1010101~~\\11111111\\=(2^{7+1}-1)\end{aligned}1010101×1110101011010101??11111111=(27+1?1)?

    101010×111010101010101111110=(26+1?2)\begin{aligned} 101010\\×11\\101010\\101010~~\\1111110\\=(2^{6+1}-2)\end{aligned}101010×11101010101010??1111110=(26+1?2)?
    總結一下就是
    2n+13\frac{2^{n+1}}{3}32n+1?


    3.3.3.感性理解,觀看四連環的例子,我們發現首先是把四連環111111111111變成兩連環110011001100,然后就可以把nnn環拿走,然后用同樣的步數變回四連環011101110111,然后就是同理去拿走n?1n-1n?1環,所以我們設f(n)f(n)f(n)表示nnn連環的方案數,那么可以表示成拿走n?2n-2n?2環的方案數然后把拿走最后一個環,把最右邊的第一個環裝回來+1+1+1,再用同樣的步數變成n?2n-2n?2環的方案數,繼續處理n?1n-1n?1環的方案數
    f(n)=f(n?1)+2?f(n?2)+1f(n)=f(n-1)+2*f(n-2)+1f(n)=f(n?1)+2?f(n?2)+1


    1≤n≤1051\le n\le 10^51n105,所以就要高精啦,然后再套一個FFTFFTFFT優化,看代碼吧,如果有任何不懂的,歡迎評論

    code

    #include <cmath> #include <cstdio> #include <cstring> #include <iostream> using namespace std; #define MAXN 80005 struct complex {double real, i;complex () {}complex ( double x, double y ) {real = x;i = y;} }; complex operator + ( complex a, complex b ) {return complex ( a.real + b.real, a.i + b.i ); } complex operator - ( complex a, complex b ) {return complex ( a.real - b.real, a.i - b.i ); } complex operator * ( complex a, complex b ) {return complex ( a.real * b.real - a.i * b.i, a.real * b.i + b.real * a.i ); } double pi = acos ( -1.0 );int rev[MAXN];void FFT ( complex *c, int f, int len ) {for ( int i = 0;i < len;i ++ )if ( i < rev[i] )swap ( c[i], c[rev[i]] );for ( int i = 1;i < len;i <<= 1 ) {complex omega ( cos ( pi / i ), f * sin ( pi / i ) );for ( int j = 0;j < len;j += ( i << 1 ) ) {complex w ( 1, 0 );for ( int k = 0;k < i;k ++, w = w * omega ) {complex x = c[j + k], y = w * c[i + j + k];c[j + k] = x + y;c[i + j + k] = x - y;}}} }struct big {int g[MAXN], len;big () {memset ( g, 0, sizeof ( g ) );len = 0;}big ( int x ) {memset ( g, 0, sizeof ( g ) );len = 0;if ( ! x ) {len = 1;return;}while ( x ) {g[len ++] = x % 10;x /= 10;}}big operator *= ( const big &b ) {static complex A[MAXN], B[MAXN];int new_len = len + b.len, limit = 1, l = 0;while ( limit < new_len ) {limit <<= 1;l ++;}for ( int i = 0;i < limit;i ++ )rev[i] = ( rev[i >> 1] >> 1 ) | ( ( i & 1 ) << ( l - 1 ) );for ( int i = 0;i < limit;i ++ ) {A[i] = complex ( i < len ? g[i] : 0, 0 );B[i] = complex ( i < b.len ? b.g[i] : 0, 0 );}FFT ( A, 1, limit );FFT ( B, 1, limit );for ( int i = 0;i < limit;i ++ )A[i] = A[i] * B[i];FFT ( A, -1, limit );static int ans[MAXN];for ( int i = 0;i < limit;i ++ )ans[i] = ( int ) ( A[i].real / limit + 0.5 );for ( int i = 0;i < limit;i ++ )if ( ans[i] > 9 ) {ans[i + 1] += ans[i] / 10;ans[i] %= 10;}-- limit;while ( limit > 0 && ans[limit] == 0 )limit --;len = ++ limit;for ( int i = 0;i < limit;i ++ )g[i] = ans[i];}big operator /= ( int x ) {int sum = 0, new_len = 0;for ( int i = len - 1;i >= 0;i -- ) {sum = ( sum << 1 ) + ( sum << 3 ) + g[i];if ( sum < x )g[i] = 0;else {if ( ! new_len ) new_len = i + 1;g[i] = sum / x;sum %= x;}}len = max ( new_len, 1 );}void print () {for ( int i = len - 1;i >= 0;i -- )printf ( "%d", g[i] );printf ( "\n" );} }result, tmp;int main() {int m, n;scanf ( "%d", &m );while ( m -- ) {scanf ( "%d", &n );n ++;result = ( 1 ), tmp = ( 2 );while ( n ) {if ( n & 1 )result *= tmp;tmp *= tmp;n >>= 1;}result /= 3;result.print();}return 0; }

    總結

    以上是生活随笔為你收集整理的[CQOI]九连环(FFT优化+高精)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。