链接:https://www.nowcoder.com/acm/contest/129/A
来源:牛客网
有一个长度为n的序列a,已知a[1]=a[n]=1,且对于2 <= x <= n,a[x] / a[x-1]是以下三个数字之一 [ 1,-2,0.5 ],问有多少种不同的序列满足题意。
两个序列不同当且仅当它们有至少一个位置上的数字不同,序列a可以为任何实数。
输入描述:
一个整数 表示n (1<= n <= 1e3)
输出描述:
一个整数 表示答案模10
9
+7
示例1
输出
复制7
题意 : 给你一个一个 n ,表示要构造的序列的长度,问最终有多少种构造序列的方式。
思路分析:注意观察要构造的序列有个特点,就是第一个和最后一个元素都是 1,所以说再变换的过程中,序列扩大和缩小的次数应该是相同的
有个很坑的地方,就是再用逆元求解的时候,分母的两个数都是取模得来的,应该分别求逆元才对
代码示例:
#define ll long long const ll maxn = 1e6+5; const ll mod = 1e9+7; ll pp[1005]; void init(){ pp[0]=1; for(ll i = 1; i <= 1000; i++){ pp[i]=pp[i-1]*i; pp[i] %= mod; } } ll inv(ll x, ll cnt){ ll ans = 1; while(cnt > 0){ if (cnt&1) ans *= x; ans %= mod; x *= x; x %= mod; cnt >>= 1; } return ans; } ll C(ll n, ll m){ ll res = pp[n]*inv(pp[m], mod-2)%mod*inv(pp[n-m], mod-2); res %= mod; return res; } int main() { //freopen("in.txt", "r", stdin); //freopen("out.txt", "w", stdout); ll n; cin >> n; init(); ll x = 0, len = n-1; ll sum=0; //printf("*** %lld ", C(20, 2)); while(x <= len/2){ sum += C(len, x)*C(len-x, x); x += 2; sum %= mod; } printf("%lld ", sum); return 0;
方法二:
直接套用组合数学的公式即可。
#define ll long long const ll maxn = 1e6+5; const ll mod = 1e9+7; ll c[1005][1005]; void init(){ c[0][0] = 1; for(int i = 1; i <= 1000; i++){ c[i][0] = c[i][i] = 1; for(int j = 1; j < i; j++){ c[i][j] = (c[i-1][j]+c[i-1][j-1])%mod; } } } int main() { //freopen("in.txt", "r", stdin); //freopen("out.txt", "w", stdout); ll n; cin >> n; init(); ll x = 0, len = n-1; ll sum=0; //printf("*** %lld ", C(20, 2)); while(x <= len/2){ sum += c[len][x]*c[len-x][x]; x += 2; sum %= mod; } printf("%lld ", sum); return 0; }