临近中考,pG的班主任决定上一节体育课,放松一下。html
题解:https://blog.csdn.net/kkkksc03/article/details/85008120web
老师带着pG的同窗们一块儿作传球游戏。app
游戏规则是这样的: n 个同窗站成一个圆圈,其中的一个同窗手里拿着一个球,当老师吹哨子时开始传球,每一个同窗能够把球传给本身左右的两个同窗中的一个(左右任意),当老师再次吹哨子时,传球中止,此时,拿着球没有传出去的那个同窗就是败者,要给你们表演一个节目。oop
pG提出一个有趣的问题:有多少种不一样的传球方法可使得从pG手里开始传的球,传了 m 次之后,又回到pG手里。两种传球方法被视做不一样的方法,当且仅当这两种方法中,接到球的同窗按接球顺序组成的序列是不一样的。好比有三个同窗 1 号、 2 号、 3 号,并假设pG为 1 号,球传了 3 次回到pG手里的方式有 1−>2−>3−>1和 1−>3−>2−>1 ,共2 种。spa
输入格式:
.net
一行,有两个用空格隔开的整数 n,mcode
输出格式:
orm
1 个整数,表示符合题意的方法数。htm
因为答案可能过大,对109+7取模。blog
对于8%的数据,n≤100,m≤104.
对于100%的数据,n≤3500,m≤109.
数据有必定梯度。
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; }