#include <bits/stdc++.h>
using namespace std;
const int N = 5e3 + 5;
const int M = 1e9 + 7;
int cuk[N];
int ile[N];
long long kombinacje[N][N];
pair <int, pair <int, int> > pref[N]; //suma na prefiksie, liczba w cuk do jakiej to sie odwoluje, nr z kolei tej liczby
int n;
long long power(long long podstawa, long long wykladnik){
if(wykladnik == 0){
return 1;
}
if(wykladnik % 2 == 0){
long long w = power(podstawa, wykladnik / 2);
return (w % M * (w % M)) % M;
}
else{
return (podstawa % M * (power(podstawa, wykladnik - 1) % M)) % M;
}
}
long long silnia(int a, int x){
long long licznik = 1, mianownik = 1;
for(int i = 1; i <= x; i++){
mianownik *= i;
mianownik %= M;
}
int pocz = max(a - x, 1);
for(int i = pocz; i <= a; i++){
licznik *= i;
licznik %= M;
}
return (licznik % M * (power(mianownik, M - 2) % M)) % M;
}
int binsearch(int p, int k, int x){
int m = (p + k) / 2;
while(p < k){
if(pref[m].first < x) p = m + 1;
else k = m;
m = (p + k) / 2;
}
return p;
}
long long przelicz(int dl){
long long wynik = 0;
int prefiks = 0;
for(int i = 1; i <= dl; i++){
if(cuk[i] == 1){
for(int j = 1; j <= ile[1]; j++){
kombinacje[1][j] += silnia(ile[1], j);
kombinacje[1][j] %= M;
wynik += kombinacje[1][j];
wynik %= M;
pref[++prefiks] = make_pair(j, make_pair(1, j));
}
continue;
}
int a = cuk[i];
if(pref[prefiks].first < a - 1){
//cout << "out " << a << "\n";
return wynik % M;
}
int poz = binsearch(1, prefiks, a - 1);
int k = prefiks;
for(int j = 1; j <= ile[a]; j++){
long long komb = silnia(ile[a], j);
//cout << a << " komb: " << komb << "\n";
for(int l = poz; l <= k; l++){
//cout << "l: " << l << "\n";
kombinacje[a][j] += ((komb % M) * (kombinacje[pref[l].second.first][ile[pref[l].second.first] - pref[l].second.second + 1]) % M) % M;
}
wynik += kombinacje[a][j];
wynik %= M;
pref[++prefiks] = make_pair(pref[prefiks].first + a, make_pair(a, j));
}
}
return wynik % M;
}
int main(){
ios_base::sync_with_stdio(false);
cin.tie(0);
cin >> n;
int poz = 1;
for(int i = 1; i <= n; i++){
long long a;
cin >> a;
if(ile[a] == 0) cuk[poz++] = a;
ile[a]++;
}
sort(cuk + 1, cuk + poz);
cout << przelicz(poz) % M;
/*for(int i = 1; i <= 7; i++){
for(int j = 1; j <= 7; j++){
cout << "\n" << "komb " << i << " " << j << " " << kombinacje[i][j];
}
}*/
/*for(int i = 1; i <= n; i++){
cout << pref[i].first << " " << pref[i].second.first << " " << pref[i].second.second << "\n";
}*/
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | #include <bits/stdc++.h> using namespace std; const int N = 5e3 + 5; const int M = 1e9 + 7; int cuk[N]; int ile[N]; long long kombinacje[N][N]; pair <int, pair <int, int> > pref[N]; //suma na prefiksie, liczba w cuk do jakiej to sie odwoluje, nr z kolei tej liczby int n; long long power(long long podstawa, long long wykladnik){ if(wykladnik == 0){ return 1; } if(wykladnik % 2 == 0){ long long w = power(podstawa, wykladnik / 2); return (w % M * (w % M)) % M; } else{ return (podstawa % M * (power(podstawa, wykladnik - 1) % M)) % M; } } long long silnia(int a, int x){ long long licznik = 1, mianownik = 1; for(int i = 1; i <= x; i++){ mianownik *= i; mianownik %= M; } int pocz = max(a - x, 1); for(int i = pocz; i <= a; i++){ licznik *= i; licznik %= M; } return (licznik % M * (power(mianownik, M - 2) % M)) % M; } int binsearch(int p, int k, int x){ int m = (p + k) / 2; while(p < k){ if(pref[m].first < x) p = m + 1; else k = m; m = (p + k) / 2; } return p; } long long przelicz(int dl){ long long wynik = 0; int prefiks = 0; for(int i = 1; i <= dl; i++){ if(cuk[i] == 1){ for(int j = 1; j <= ile[1]; j++){ kombinacje[1][j] += silnia(ile[1], j); kombinacje[1][j] %= M; wynik += kombinacje[1][j]; wynik %= M; pref[++prefiks] = make_pair(j, make_pair(1, j)); } continue; } int a = cuk[i]; if(pref[prefiks].first < a - 1){ //cout << "out " << a << "\n"; return wynik % M; } int poz = binsearch(1, prefiks, a - 1); int k = prefiks; for(int j = 1; j <= ile[a]; j++){ long long komb = silnia(ile[a], j); //cout << a << " komb: " << komb << "\n"; for(int l = poz; l <= k; l++){ //cout << "l: " << l << "\n"; kombinacje[a][j] += ((komb % M) * (kombinacje[pref[l].second.first][ile[pref[l].second.first] - pref[l].second.second + 1]) % M) % M; } wynik += kombinacje[a][j]; wynik %= M; pref[++prefiks] = make_pair(pref[prefiks].first + a, make_pair(a, j)); } } return wynik % M; } int main(){ ios_base::sync_with_stdio(false); cin.tie(0); cin >> n; int poz = 1; for(int i = 1; i <= n; i++){ long long a; cin >> a; if(ile[a] == 0) cuk[poz++] = a; ile[a]++; } sort(cuk + 1, cuk + poz); cout << przelicz(poz) % M; /*for(int i = 1; i <= 7; i++){ for(int j = 1; j <= 7; j++){ cout << "\n" << "komb " << i << " " << j << " " << kombinacje[i][j]; } }*/ /*for(int i = 1; i <= n; i++){ cout << pref[i].first << " " << pref[i].second.first << " " << pref[i].second.second << "\n"; }*/ } |
English