zoukankan      html  css  js  c++  java
  • hdu4935 Prime Tree(2014多校联合第七场)

    首先这是一道dp题,对题意的把握和对状态的处理是解题关键。

    题目给出的范围是n在1到1e11之间,由于在裂变过称中左儿子总是父亲节点的一个非平凡约数,容易看出裂变过程只与

    素数幂有关,并且显然有素数不超过11个,幂指数不超过40,实际上可以用一个大小为11的数组来等价地表示状态,状态

    与其内元素顺序无关,因此可以排序,压缩后的状态不超过3000个(准确地说是2957个,通过一个简单的dfs即可统计出此结果)。

    以上解决了题目的规模问题。

    这道题目我开始因为理解错题意wa了几次,不能通过统计儿子节点的期望高度的平均值再加1得到以父节点为根的数的期望高度,因为两颗子树

    的高度在概率上对根树的影响不是相互独立的。

    可以设dp(i, j)为以状态i为根深度为j的概率:

    那么显然有dp(i, j) = sigma(dp(k, j - 1) * sigma(i / k, t) + sigma(k, t) * dp(i / k, j - 1) + dp(k, j - 1) * dp(i / k, j -1)) / (N - 2)

    其中k | i, 且 k ≠ 1,k≠ i, t < j - 1。

    以状态i为根的树的期望高度:exp(i) = sigma(j * dp(i, j)), 0 < j < 40.

    因此状态转移可以通过枚举左儿子得到,整体复杂度O(3000 * 3000 * 40)。

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <algorithm>
      4 #include <map>
      5 #include <string>
      6 #include <vector>
      7 #include <set>
      8 #include <cmath>
      9 #include <ctime>
     10 #include <cassert>
     11 #pragma comment(linker, "/STACK:102400000,102400000")
     12 #define lson (u << 1)
     13 #define rson (u << 1 | 1)
     14 #define cls(i, j) memset(i, j, sizeof i)
     15 using namespace std;
     16 typedef __int64 ll;
     17 const double eps = 1e-6;
     18 const double pi = acos(-1.0);
     19 const int maxn = 1e5 + 10;
     20 const int maxm = 1050;
     21 const int inf = 0x3f3f3f3f;
     22 const ll linf = 0x3fffffffffffffff;
     23 const ll mod = 1e9 + 7;
     24 
     25 int debug = 0;
     26 map<ll, int> mapi;
     27 int buf[11], k1;
     28 ll S = (ll)1e11;
     29 double dp[3000][40];
     30 
     31 int a[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31};
     32 bool cmp(int a, int b) { return a > b; }
     33 int prime[maxn], k;
     34 bool vis[3000];
     35 
     36 ll Hash(int *t){
     37     ll tem = 1, ans = 0;
     38     for(int i = 0; i < 11; i++){
     39         ans += tem * t[i];
     40         tem *= 37;
     41     }
     42     return ans;
     43 }
     44 
     45 int stack[11], k2;
     46 ll states[3000];
     47 int ks;
     48 int table[3500][11];
     49 
     50 void dfs(ll num, int limit, int next){
     51     if(next){
     52         memcpy(buf, stack, sizeof buf);
     53         sort(buf, buf + 11, cmp);
     54         ll hash_value = Hash(buf);
     55         states[ks++] = hash_value;
     56         memcpy(table[ks - 1], buf, sizeof buf);
     57         mapi[hash_value] = ks - 1;
     58     }
     59     if(next > 10) return;
     60     for(int i = 1; i <= limit; i++){
     61         num *= a[next];
     62         if(num > S) break;
     63         stack[k2++] = i;
     64         dfs(num, i, next + 1);
     65         stack[--k2] = 0;
     66     }
     67 }
     68 
     69 void shaffix(){
     70     bool vis[500000 + 10];
     71     int mid = (int)5e5 + 10;
     72     cls(vis, 0);
     73     for(int i = 2; i < mid; i++){
     74         if(vis[i]) continue;
     75         prime[k++] = i;
     76         for(ll j = (ll)i * 2; j < mid; j += i) vis[j] = 1;
     77     }
     78 }
     79 
     80 void cal(int id);
     81 
     82 void dfs1(int id, int next){
     83     if(next > 10){
     84         int buf1[11], buf2[11];
     85         memcpy(buf1, stack, sizeof stack);
     86         for(int i = 0; i < 11; i++) buf2[i] = table[id][i] - buf1[i];
     87         sort(buf1, buf1 + 11, cmp);
     88         sort(buf2, buf2 + 11, cmp);
     89         if(!buf1[0] || !buf2[0]) return;
     90         ll hash_value1 = Hash(buf1), hash_value2 = Hash(buf2);
     91         int id1 = mapi[hash_value1], id2 = mapi[hash_value2];
     92         cal(id1), cal(id2);
     93         double prefix_left = 0, prefix_right = 0;
     94         for(int i = 0; i < 39; i++){
     95             dp[id][i + 1] += dp[id1][i] * prefix_right +
     96             prefix_left * dp[id2][i] + dp[id1][i] * dp[id2][i];
     97             prefix_left += dp[id1][i], prefix_right += dp[id2][i];
     98         }
     99         return;
    100     }
    101     for(int i = 0; i <= table[id][next]; i++){
    102         stack[k2++] = i;
    103         dfs1(id, next + 1);
    104         stack[--k2] = 0;
    105     }
    106 }
    107 
    108 void cal(int id){
    109     if(vis[id]) return;
    110     k2 = 0;
    111     dfs1(id, 0);
    112     int sum = 1;
    113     for(int i = 0; i < 11; i++) sum *= 1 + table[id][i];
    114     sum -= 2;
    115     for(int i = 1; i < 40; i++) dp[id][i] /= sum;
    116     vis[id] = 1;
    117     //printf("%d+
    ", id);
    118 }
    119 
    120 void init(){
    121     shaffix();
    122     cls(vis, 0);
    123     vis[0] = 1;
    124     mapi.clear();
    125     //0...10 < 10^11
    126     cls(stack, 0);
    127     ks = k2 = 0;
    128     dfs(1, 40, 0);
    129     cls(dp, 0);
    130     dp[0][1] = 1;
    131     for(int i = 1; i < ks; i++) cal(i);
    132 }
    133 
    134 double solve(ll num){
    135     cls(buf, 0);
    136     k1 = 0;
    137     int mid = (int)sqrt((double)num);
    138     for(int i = 0; i < k && prime[i] <= mid; i++){
    139         if(num % prime[i]) continue;
    140         while(num % prime[i] == 0) ++buf[k1], num /= prime[i];
    141         mid = (int)sqrt((double)num);
    142         k1++;
    143     }
    144     if(num != 1) buf[k1++] = 1;
    145     sort(buf, buf + 11, cmp);
    146     ll hash_value = Hash(buf);
    147     double ans = 0;
    148     int id = mapi[hash_value];
    149     for(int i = 1; i < 40; i++) ans += dp[id][i] * i;
    150     return ans;
    151 }
    152 
    153 int main(){
    154     //freopen("in.txt", "r", stdin);
    155     //freopen("out.txt", "w", stdout);
    156     int T, kase = 0;
    157     init();
    158     scanf("%d", &T);
    159     ll n;
    160     while(T--){
    161         scanf("%I64d", &n);
    162         double ans = solve(n);
    163         printf("Case #%d: %.6f
    ", ++kase, ans);
    164     }
    165     return 0;
    166 }
    View Code
  • 相关阅读:
    python time 转换&运算tips
    Web.py session用户认证
    简单的内存池实现gko_alloc
    cpp(第十章)
    cpp(第九章)
    cpp(第八章)
    cpp(第七章)
    cpp(第六章)
    cpp(第五章)
    结构中的位字段
  • 原文地址:https://www.cnblogs.com/astoninfer/p/4947470.html
Copyright © 2011-2022 走看看