zoukankan      html  css  js  c++  java
  • 模拟33 题解

    A. 春思

    比较简单的一道题,甚至是见过的原题。

    约数和是积性函数,搞一搞等差数列求和,乘到一起就可以了。

    B. 密州盛宴

    显然,方案合法的条件是苏轼每轮都能吃到菜。

    所以就发现任意后缀0,1个数必须满足,$sufcnt_0-sufcnt_1<=1$。

    所以当不满足条件时找到第一个1,把他交换过来,答案对两者之间的距离取max,显然这样能得到一个最优答案。

    左侧用单调指针,复杂度$O(n)$,过不去。

    然后就发现,直接对$sufcnt0-sufcnt1$取个$max$,然后输出$max-1$就可以了。

    这个取max的操作是等价于上述的单调指针算法的。

    因为任何交换不影响交换之前的点的$sufcnt$,

    一个交换,两点之间的距离一定可以表示为交换的1的$sufcnt_0-sufcnt_1-1$。

    C. 赤壁情

    比较新奇的dp题。

    设$dp(i,j,k,0/1/2)$表示已经插入i个数,形成了j段连续的数,这些数构成的权值为k,已经有了0/1/2个数在l或r边界上的方案数。

    值得注意的一点是,利用先插入的数小于后插入的数的值的性质,

    我们将已经插入的数的贡献直接算在了权值中,而不是构成差时再加入,这样才使状态没有了后效性。

    另外,我们在dp的过程中,并不确定每一段的具体位置,只知道它们之间的左右位置关系,和是否接在端点。

    在插入了最后一个数,对于合法方案,具体位置才得到确定。

    五个转移方程,分别对应:

    接在一段旁边,

    连接两段,

    单独成一段,

    放在端点并接上一段,

    单独放在端点。

    在转移中乘上每个方程对应的系数就可以了。

    要求保留30位小数,用高精度。

    在作除法之前将答案左移31位(十进制),第31位表示小数点后的第一位。

    最后根据最后一位的大小决定是否要进位。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<iomanip>
      5 using namespace std;
      6 int n,m,k;
      7 namespace DOUBLE{
      8     const int N=105;
      9     double dp[2][N*N][N/2][3],ans;
     10     void go(){
     11         int cur=1; const int base=n*(n+1)/2;
     12         dp[cur][base-2][1][0]=1;
     13         dp[cur][base-1][1][1]=2;
     14         dp[cur][base][1][2]=1;
     15         for(int i=2;i<=n;++i){
     16             cur^=1;
     17             const int lm=min(i,n-i+1)+1;
     18             for(int j=0;j<=2*base;++j)
     19                 for(int k=1;k<=lm;++k)
     20                     for(int u=0;u<3;++u) dp[cur][j][k][u]=0;
     21             for(int j=0;j<=2*base;++j)
     22                 for(int k=1;k<=lm;++k)
     23                     for(int u=0;u<3;++u){
     24                         dp[cur][j][k][u]+=dp[cur^1][j][k][u]*(k*2-u);//接在后面
     25                         if(j+2*i<=2*base) dp[cur][j+2*i][k-1][u]+=dp[cur^1][j][k][u]*(k-1);//合并
     26                         if(j-2*i>=0) dp[cur][j-2*i][k+1][u]+=dp[cur^1][j][k][u]*(k+1-u);//单独
     27                         if(j+i<=2*base&&u!=2) dp[cur][j+i][k][u+1]+=dp[cur^1][j][k][u]*(2-u);//接在一端
     28                         if(j-i>=0&&u!=2) dp[cur][j-i][k+1][u+1]+=dp[cur^1][j][k][u]*(2-u);//在一端单独开
     29                     }
     30         }
     31         for(int i=m+base;i<=2*base;++i) ans+=dp[cur][i][1][2];
     32         for(int i=1;i<=n;++i) ans/=i;
     33         cout<<fixed<<setprecision(k)<<ans<<endl;
     34     }
     35 }
     36 namespace BIGINT{
     37     const int N=55;
     38     struct BigInteger{
     39         const static long long base=1e10;
     40         long long s[12];
     41         int num;
     42         void set(int x){
     43             memset(s,0,sizeof(s));
     44             s[num=1]=x;
     45         }
     46         friend void operator +=(BigInteger &a,BigInteger b){
     47             a.num=max(a.num,b.num);
     48             for(int i=1;i<=a.num;++i){
     49                 a.s[i]+=b.s[i];
     50                 if(a.s[i]>=base) a.s[i]-=base,++a.s[i+1];
     51             }
     52             if(a.s[a.num+1]) ++a.num;
     53         }
     54         friend BigInteger operator *(BigInteger a,int x){
     55             int j=0;
     56             for(int i=1;i<=a.num;++i){
     57                 a.s[i]=a.s[i]*x+j;
     58                 j=a.s[i]/base;
     59                 a.s[i]%=base;
     60             }
     61             if(j) a.s[++a.num]=j;
     62             return a;
     63         }
     64         friend void operator /=(BigInteger &a,int x){
     65             for(int i=a.num;i;--i){
     66                 a.s[i-1]+=a.s[i]%x*base;
     67                 a.s[i]/=x;
     68             }
     69             if(!a.s[a.num]) --a.num;
     70         }
     71     };
     72     BigInteger dp[2][N*N][N/2][3],ans;
     73     void go(){
     74         int cur=1; const int base=n*(n+1)/2;
     75         dp[cur][base-2][1][0].set(1);
     76         dp[cur][base-1][1][1].set(2);
     77         dp[cur][base][1][2].set(1);
     78         for(int i=2;i<=n;++i){
     79             cur^=1;
     80             const int lm=min(i,n-i+1)+1;
     81             for(int j=0;j<=2*base;++j)
     82                 for(int k=1;k<=lm+1;++k)
     83                     for(int u=0;u<3;++u) dp[cur][j][k][u].set(0);
     84             for(int j=0;j<=2*base;++j)
     85                 for(int k=1;k<=lm;++k)
     86                     for(int u=0;u<3;++u){
     87                         dp[cur][j][k][u]+=dp[cur^1][j][k][u]*(k*2-u);//接在后面
     88                         if(j+2*i<=2*base) dp[cur][j+2*i][k-1][u]+=dp[cur^1][j][k][u]*(k-1);//合并
     89                         if(j-2*i>=0) dp[cur][j-2*i][k+1][u]+=dp[cur^1][j][k][u]*(k+1-u);//单独
     90                         if(j+i<=2*base&&u!=2) dp[cur][j+i][k][u+1]+=dp[cur^1][j][k][u]*(2-u);//接在一端
     91                         if(j-i>=0&&u!=2) dp[cur][j-i][k+1][u+1]+=dp[cur^1][j][k][u]*(2-u);//在一端单独开
     92                     }
     93         }
     94         for(int i=m+base;i<=2*base;++i) ans+=dp[cur][i][1][2];
     95         for(int i=1;i<=k+10;++i) ans=ans*10;
     96         for(int i=1;i<=n;++i) ans/=i;
     97         if(ans.s[1]>=ans.base/2) ++ans.s[2];
     98         for(int i=2;i<=ans.num;++i)
     99             if(ans.s[i]>=ans.base) ans.s[i]-=ans.base,++ans.s[i+1];
    100         printf("%lld.",ans.s[5]);
    101         for(int i=4;i>1;--i) printf("%010lld",ans.s[i]);
    102         puts("");
    103     }
    104 }
    105 int main(){
    106     scanf("%d%d%d",&n,&m,&k);
    107     if(k>=10) BIGINT::go();
    108     else DOUBLE::go();
    109     return 0;
    110 }
    View Code
  • 相关阅读:
    JZOJ 3034. 【NOIP2012模拟10.17】独立集
    JZOJ 3035. 【NOIP2012模拟10.17】铁轨
    JZOJ 1259. 牛棚安排
    数位DP JZOJ 3316. 非回文数字
    JZOJ 3046. 游戏
    JZOJ 3013. 填充棋盘
    debian 安装oracle提供的java8
    java 汉字转拼音 PinYin4j
    debian ssh设置root权限登陆 Permission denied, please try again
    java并发下订单生成策略
  • 原文地址:https://www.cnblogs.com/skyh/p/11451884.html
Copyright © 2011-2022 走看看