zoukankan      html  css  js  c++  java
  • noip模拟测试15


    T1:建设城市(city)

      第一眼看是组合,然后看到k的限制发现是容斥

      用插板法加容斥得出:$sum_{i=0}^{m-i*k-1 leq n-1}C_n^i*C_{m-i*k-1}^{n-1}*(-1)^i$

      但发现$n$的范围是$10^9$,组合数计算是$O(n)$的

      但又发现$m$的范围是$10^7$,所以特判$n>m$的情况就行了

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<algorithm>
     6 #include<vector>
     7 #include<queue>
     8 #define ll long long
     9 using namespace std;
    10 const int MAXN=10000005;
    11 const ll D=998244353;
    12 ll n,m,k,ans,fac[MAXN],inv[MAXN];
    13 ll qpow(ll x,ll k) {
    14     ll ret=1;
    15     while(k) {
    16         if(k&1) ret=ret*x%D;
    17         x=x*x%D;
    18         k>>=1;
    19     }
    20     return ret;
    21 }
    22 void first() {
    23     fac[0]=inv[0]=1;
    24     for(int i=1;i<=m;i++)
    25         fac[i]=fac[i-1]*i%D;
    26     inv[m]=qpow(fac[m],D-2);
    27     for(int i=m-1;i>=1;i--)
    28         inv[i]=inv[i+1]*(i+1)%D;
    29 }
    30 ll C(int x,int y) {
    31     return fac[x]*inv[x-y]%D*inv[y]%D;
    32 }
    33 int main() {
    34     scanf("%lld%lld%lld",&n,&m,&k);
    35     if(n>m||m>n*k) {
    36         printf("0
    ");
    37         return 0;
    38     } else if(n==m||m==n*k) {
    39         printf("1
    ");
    40         return 0;
    41     }
    42     first();
    43     ans=C(m-1,n-1);
    44     for(ll i=1;;i++) {
    45         if(m-i*k-1<n-1) break;
    46         if(i&1) ans=(ans-C(n,i)*C(m-i*k-1,n-1))%D;
    47         else ans=(ans+C(n,i)*C(m-i*k-1,n-1))%D;
    48     }
    49     printf("%lld
    ",(ans%D+D)%D);
    50     return 0;
    51 }
    t1 Code


    T2: 轰炸行动(bomb)

      读题出锅……

      就是简单的tarjan,缩完scc后跑个拓扑求点权的最长链就行了

      自己手玩几组数据就知道了

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<algorithm>
     6 #include<vector>
     7 #include<queue>
     8 #include<bitset>
     9 #define ll long long
    10 using namespace std;
    11 const int MAXN=1100000,INF=0x3f3f3f3f;
    12 int n,m,ans,dfn[MAXN],low[MAXN],stk[MAXN],tp,num;
    13 int scc_cnt,scc[MAXN],siz[MAXN],du[MAXN],f[MAXN];
    14 bool vis[MAXN];
    15 struct edge {
    16     int x,y;
    17 }e[MAXN];
    18 struct node {
    19     int to,nxt;
    20 }mp[MAXN];
    21 int h[MAXN],tot;
    22 void add(int x,int y) {
    23     mp[++tot].to=y;
    24     mp[tot].nxt=h[x];
    25     h[x]=tot;
    26 }
    27 void tarjan(int u) {
    28     dfn[u]=low[u]=++num;
    29     stk[++tp]=u;vis[u]=1;
    30     for(int i=h[u];i;i=mp[i].nxt) {
    31         int v=mp[i].to;
    32         if(!dfn[v]) {
    33             tarjan(v);
    34             low[u]=min(low[u],low[v]);
    35         } else if(vis[v]) low[u]=min(low[u],dfn[v]);
    36     }
    37     if(dfn[u]==low[u]) {
    38         ++scc_cnt;
    39         int tmp;
    40         do {
    41             tmp=stk[tp--];
    42             vis[tmp]=0;
    43             siz[scc_cnt]++;
    44             scc[tmp]=scc_cnt;
    45         }while(tmp!=u);
    46     }
    47 }
    48 void build() {
    49     memset(h,0,sizeof(h));tot=0;
    50     for(int i=1;i<=m;i++)
    51         if(scc[e[i].x]!=scc[e[i].y]) {
    52             add(scc[e[i].x],scc[e[i].y]);
    53             du[scc[e[i].y]]++;
    54         }
    55 }
    56 void topo() {
    57     queue<int> q;
    58     for(int i=1;i<=scc_cnt;i++)
    59         if(!du[i]) q.push(i);
    60     while(!q.empty()) {
    61         int u=q.front(); q.pop();
    62         f[u]+=siz[u];
    63         for(int i=h[u];i;i=mp[i].nxt) {
    64             int v=mp[i].to;
    65             f[v]=max(f[v],f[u]);
    66             if(!--du[v]) q.push(v);
    67         }
    68     }
    69 }
    70 int main() {
    71     scanf("%d%d",&n,&m);
    72     for(int i=1;i<=m;i++) {
    73         scanf("%d%d",&e[i].x,&e[i].y);
    74         add(e[i].x,e[i].y);
    75     }
    76     for(int i=1;i<=n;i++)
    77         if(!dfn[i]) tarjan(i);
    78     build();
    79     topo();
    80     for(int i=1;i<=scc_cnt;i++) ans=max(ans,f[i]);
    81     printf("%d
    ",ans);
    82     return 0;
    83 }
    t2 Code


    T3:石头剪刀布(rps)

      懵比……

      设计$g[t][i][j][k]$表示前t个人,出i个石头,j个布子,k个剪刀的概率

      则$g[t][i][j][k]=g[t-1][i][j][k]+g[t-1][i-1][j][k]*r[t]+g[t-1][i][j-1][k]*p[t]+g[t-1][i][j][k-1]*s[t]$

      即上一层出i,j,k的概率加上少出一个石头/布子/剪刀,然后这次再出一个的概率

      再设计$f[i][j][k][0/1/2]$表示前i+j+k次中出i个石头,j个布子,k个剪刀,且下一次会出0/1/2->石头/布子/剪刀的概率

      则$f[i][j][k][0]=f[i-1][j][k][0]*r[t]+f[i][j-1][k][0]*p[t]+f[i][j][k-1][0]*s[t]+g[t-1][i][j][k][0]*r[t]$

       $f[i][j][k][1]=f[i-1][j][k][1]*r[t]+f[i][j-1][k][1]*p[t]+f[i][j][k-1][1]*s[t]+g[t-1][i][j][k][1]*p[t]$

       $f[i][j][k][2]=f[i-1][j][k][2]*r[t]+f[i][j-1][k][2]*p[t]+f[i][j][k-1][2]*s[t]+g[t-1][i][j][k][2]*s[t]$

      即:分别考虑新来的这个人t在合适出来,打出什么

       第一个式子中:

       $f[i-1][j][k][0]*r[t]+f[i][j-1][k][0]*p[t]+f[i][j][k-1][0]*s[t]$

        表示t这个人在猜拳序列的中间出现,则对下一次出什么没有影响

       $g[t-1][i][j][k-1]*s[t]$

        表示t这个人在序列的最后出现,则与前面人怎么出无关,而与它出什么有关

       后两个式子也是一样的

      最后统计答案时枚举$i,j,k(i+j+k<n)$

      答案为$sum max (3*f[i][j][k][0/1/2]+f[i][j][k][1/2/0]) / (C_n^{i+j+k} * (n-i-j-k))$

      即:分别决策每种情况出什么最优,将最大期望得分除以总方案数累加起来

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<algorithm>
     6 #include<vector>
     7 #include<queue>
     8 #include<bitset>
     9 #define ld long double
    10 using namespace std;
    11 const int MAXN=55;
    12 int n;
    13 ld C[MAXN][MAXN];
    14 ld r[MAXN],p[MAXN],s[MAXN],ans;
    15 ld f[MAXN][MAXN][MAXN][3],g[MAXN][MAXN][MAXN][MAXN];
    16 int main() {
    17     scanf("%d",&n);
    18     for(int i=1;i<=n;i++) scanf("%Lf%Lf%Lf",&r[i],&p[i],&s[i]);
    19     for(int i=1;i<=n;i++) {
    20         r[i]/=300.0;
    21         p[i]/=300.0;
    22         s[i]/=300.0;
    23     }
    24     for(int i=0;i<=n;i++) {
    25         C[i][0]=1;
    26         for(int j=1;j<=i;j++)
    27             C[i][j]=C[i-1][j]+C[i-1][j-1];
    28     }
    29     g[0][0][0][0]=1;
    30     for(int t=1;t<=n;t++)
    31         for(int i=t;i>=0;i--)
    32             for(int j=t-i;j>=0;j--)
    33                 for(int k=t-i-j;k>=0;k--) {
    34                     g[t][i][j][k]=g[t-1][i][j][k];
    35                     if(i)g[t][i][j][k]+=g[t-1][i-1][j][k]*r[t];
    36                     if(j)g[t][i][j][k]+=g[t-1][i][j-1][k]*p[t];
    37                     if(k)g[t][i][j][k]+=g[t-1][i][j][k-1]*s[t];
    38                 }
    39     for(int t=1;t<=n;t++)
    40         for(int i=t;i>=0;i--)
    41             for(int j=t-i;j>=0;j--)
    42                 for(int k=t-i-j;k>=0;k--) {
    43                     if(i) {
    44                         f[i][j][k][0]+=f[i-1][j][k][0]*r[t];
    45                         f[i][j][k][1]+=f[i-1][j][k][1]*r[t];
    46                         f[i][j][k][2]+=f[i-1][j][k][2]*r[t];
    47                     }
    48                     if(j) {
    49                         f[i][j][k][0]+=f[i][j-1][k][0]*p[t];
    50                         f[i][j][k][1]+=f[i][j-1][k][1]*p[t];
    51                         f[i][j][k][2]+=f[i][j-1][k][2]*p[t];
    52                     }
    53                     if(k) {
    54                         f[i][j][k][0]+=f[i][j][k-1][0]*s[t];
    55                         f[i][j][k][1]+=f[i][j][k-1][1]*s[t];
    56                         f[i][j][k][2]+=f[i][j][k-1][2]*s[t];
    57                     }
    58                     f[i][j][k][0]+=g[t-1][i][j][k]*r[t];
    59                     f[i][j][k][1]+=g[t-1][i][j][k]*p[t];
    60                     f[i][j][k][2]+=g[t-1][i][j][k]*s[t];
    61                 }
    62     for(int i=0;i<n;i++)
    63         for(int j=0;i+j<n;j++)
    64             for(int k=0;i+j+k<n;k++) {
    65                 ld tmp=0.0;
    66                 tmp=f[i][j][k][0]*3+f[i][j][k][1];
    67                 tmp=max(tmp,f[i][j][k][1]*3+f[i][j][k][2]);
    68                 tmp=max(tmp,f[i][j][k][2]*3+f[i][j][k][0]);
    69                 ans+=tmp/(C[n][i+j+k]*(n-i-j-k));
    70             }
    71     printf("%.12Lf
    ",ans);
    72     return 0;
    73 }
    t3 Code

       

  • 相关阅读:
    IO流上机作业
    数据结构堆排序
    数据结构实训报告
    字符串的基本操作
    java窗口的简单切换
    判断一个串B位于串A的位置
    c语言实现数组转置,加减,乘法运算
    java异常处理
    弹奏乐器
    课程总结
  • 原文地址:https://www.cnblogs.com/Gkeng/p/11326961.html
Copyright © 2011-2022 走看看