P5173 傳球

 

題目背景

臨近中考,pG的班主任決定上一節體育課,放鬆一下。html

題解:https://blog.csdn.net/kkkksc03/article/details/85008120web

題目描述

老師帶着pG的同窗們一塊兒作傳球遊戲。app

遊戲規則是這樣的: nn 個同窗站成一個圓圈,其中的一個同窗手裏拿着一個球,當老師吹哨子時開始傳球,每一個同窗能夠把球傳給本身左右的兩個同窗中的一個(左右任意),當老師再次吹哨子時,傳球中止,此時,拿着球沒有傳出去的那個同窗就是敗者,要給你們表演一個節目。oop

pG提出一個有趣的問題:有多少種不一樣的傳球方法可使得從pG手裏開始傳的球,傳了 mm 次之後,又回到pG手裏。兩種傳球方法被視做不一樣的方法,當且僅當這兩種方法中,接到球的同窗按接球順序組成的序列是不一樣的。好比有三個同窗 11 號、 22 號、 33 號,並假設pG爲 11 號,球傳了 33 次回到pG手裏的方式有 1 -> 2 -> 3 -> 11−>2>3>1和 1 -> 3 -> 2 -> 11−>3>2>1 ,共22 種。spa

輸入輸出格式

輸入格式:
 .net

 

一行,有兩個用空格隔開的整數 n,mn,mcode

 

輸出格式:
 orm

 

11 個整數,表示符合題意的方法數。htm

因爲答案可能過大,對10^9+7109+7取模。blog

 

輸入輸出樣例

輸入樣例#1:  複製
3 3
輸出樣例#1:  複製
2
輸入樣例#2:  複製
30 30
輸出樣例#2:  複製
155117522
輸入樣例#3:  複製
1234 12345678
輸出樣例#3:  複製
424074635

說明

對於8%的數據,n \le 100,m \le 10^4n100,m104.

對於100%的數據,n \le 3500,m \le 10^9n3500,m109.

數據有必定梯度。

【題意】

n個石子堆排成一排,每次能夠將連續的最少L堆,最多R堆石子合併在一塊兒,消耗的代價爲要合併的石子總數。

求合併成1堆的最小代價,若是沒法作到輸出0

 

【分析】

思路0:

TLE(8分)

    cin>>n>>m;
    f[0][0]=1;
    for(int i=1;i<=m;i++){
        for(int j=0;j<n;j++){
            f[i&1][j]=(f[i-1&1][(j-1+n)%n]+f[i-1&1][(j+1)%n])%mod;
        }
    }
    cout<<f[m&1][0];

 

思路1:

 

 

思路2:

 

 

 

思路3:

 ——摘自洛谷

 

【代碼】

 思路3的

#pragma GCC optimize("Ofast,fast-math,unroll-loops")
#include<cstdio>
#include<cstring>
using namespace std;
const int N=10000|1;
const int mod=1e9+7;
int n,m,a[N],ans[N];
inline void plusx(int &x,int y){
    x+=y;if(x>=mod) x-=mod;
}
inline void PolyMul(int *a,int *b,int *c){
    int t[N];memset(t,0,sizeof(int)*(n<<1));
    for(int i=0;i<n;i++){
        if(a[i]){
            for(int j=0;j<n;j++){
                plusx(t[i+j],(long long)a[i]*b[j]%mod);
            }
        }
    }
    for(int i=0;i<n;i++) c[i]=t[i];
    for(int i=n;i<n<<1;i++) plusx(c[i-n],t[i]);
}
int main(){
    scanf("%d%d",&n,&m);
    a[1]=a[n-1]=1;ans[0]=1;
    for(;m;m>>=1,PolyMul(a,a,a)) if(m&1) PolyMul(ans,a,ans);
    printf("%d",ans[0]);
    return 0;
} 
相關文章
相關標籤/搜索