HNOI2002]彩票

嘟嘟嘟html

 

遇到這種無從下手且數據範圍特別小的題,直接一波爆搜加剪枝就好了。git

爆搜就是選到的數是嚴格從大到小的,這樣才能保證複雜度是C(n, m)的,而後枚舉每個數是選了仍是沒選。ide

剪枝有這麼幾點。spa

1.若是當前值比x / y大,返回(顯然~)。htm

2.若是當前值加上最小值仍比x / y大,返回。get

3.若是當前值加上最大值仍比x / y小,返回。it

至於加上最大值最小值,能夠下預處理倒數和的前綴和,而後最小值就是sum[m - (n - step), m],最大值就是sum[num + n - step - 1, num],其中num表示枚舉到序列中的第num個數,step表示選了step個數。ast

 1 #include 2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 #include 9 #include10 #include11 using namespace std;12 #define enter puts("") 
13 #define space putchar(' ')14 #define Mem(a) memset(a, 0, sizeof(a))15 typedef long long ll;16 typedef double db;17 const int INF = 0x3f3f3f3f;18 const db eps = 1e-10;19 const int maxn = 55;20 inline ll read()21 {22     ll ans = 0;23     char ch = getchar(), last = ' ';24     while(!isdigit(ch)) {last = ch; ch = getchar();}25     while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}26     if(last == '-') ans = -ans;27     return ans;28 }29 inline void write(ll x)30 {31     if(x < 0) x = -x, putchar('-');32     if(x >= 10) write(x / 10);33     putchar(x % 10 + '0');34 }35 36 int n, m, x, y;37 db ans, Sum[maxn];38 ll tot = 0;39 40 void dfs(int num, int step, db sum)41 {42     db Min = sum + Sum[m] - Sum[m - (n - step)];43     db Max = sum + Sum[num + n - step - 1] - Sum[num - 1];44     if(Min > ans + eps || Max < ans - eps) return;45     if(step == n) {tot++; return;}46     if(num == m + 1) return;47     dfs(num + 1, step, sum);48     dfs(num + 1, step + 1, sum + 1.0 / (db)num);49 }50 51 52 int main()53 {54     n = read(); m = read(); x = read(); y = read();55     ans = (db)x / (db)y;56     for(int i = 1; i <= m; ++i) Sum[i] = Sum[i - 1] + 1.00 / (db)i;57     dfs(1, 0, 0.0);58     write(tot); enter;59     return 0;60 }

View Codeclass

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息