[NOI.AC] count
阿新 • • 發佈:2018-09-22
getchar code main 如果 ans sign lse ++ ...
思路:
考慮組合數學。
當所求中沒有重復的時候,方案數就是\(C_{n + 1}^{k}\)
當有重復的時候...
設相等的數字之間的距離為\(len\)
當取0個數時,方案數就是\(C_{n - 1}^{k}\)
取1個數時,方案數大概是\(2 * C_{n - 1}^{k - 1}\) ,但是如果相同的數字之間那一段沒有取任何一個其他的數,那麽取任意一個相同的數都是等價的,所以要減去\(C_{n - len}^{i - 1}\)
取了兩個數,方案數就是\(C_{n - 1}^{k - 2}\)
考試炸了範圍...
#include <bits/stdc++.h> using namespace std; #define ll long long #define int long long const int maxn = 200010; const int mod = 1e9+7; int n; inline int pow_mod(int x,int y) { int res = 1; while(y) { if(y & 1) res = res * x % mod; x = x * x % mod; y >>= 1; } return res % mod; } inline int read() { int q=0,f=1;char ch = getchar(); while(!isdigit(ch)){ if(ch==-'-')f=-1;ch=getchar(); } while(isdigit(ch)){ q=q*10+ch-'0';ch=getchar(); } return q*f; } int fac[maxn]; int a[maxn]; int vis[maxn]; int ifac[maxn]; inline int C(int x,int y) { if(x < y) return 0; if(y < 0) return 0; return fac[x] * ifac[y] % mod * ifac[x - y] % mod; } int len; int ans[maxn]; inline void pre () { fac[0] = 1; for(int i = 1;i <= n + 1; ++i) { fac[i] = fac[i - 1] * i % mod; } ifac[n + 1] = pow_mod(fac[n + 1],mod - 2); for(int i = n;i >= 0; --i) { ifac[i] = ifac[i + 1] * (i + 1) % mod; } } signed main () { n = read(); for(int i = 1;i <= n + 1; ++i) { a[i] = read(); if(vis[a[i]] == 0) { vis[a[i]] = i; } else len = i - vis[a[i]] + 1; } pre(); for(int i = 1;i <= n + 1; ++i) { int res = C(n - 1,i); res = (res + 2 * C(n - 1,i - 1)) % mod; res = (res - C(n - len + 1,i - 1) + mod) % mod; res = (res + C(n - 1,i - 2)) % mod; ans[i] = res; } for(int i = 1;i <= n + 1; ++i) printf("%lld\n",ans[i]); return 0; }
[NOI.AC] count