zoukankan      html  css  js  c++  java
  • 模拟15 题解(waiting)

    T1

    60%算法

    定义f[i][j]表示枚举到i位置,已经使用过了j个队,

    $f[i][j]+=f[i-1][t] ( t in [max(0,j-k),j])$滚动一下

    这是个O(n^3)的,考虑如何优化,发现可以使用前缀和,避免枚举t,$O(n^2)$

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<algorithm>
     6 #define R register
     7 #define ll long long
     8 using namespace std;
     9 inline int read()
    10 {
    11     int f=1,x=0;char ch=getchar();
    12     while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    13     while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    14     return f*x;
    15 }
    16 const int mod=998244353;
    17 const int maxn=10000005;
    18 int n,m,k;
    19 ll f[2][maxn],g[2][maxn];
    20 int main()
    21 {
    22     //freopen("data1","r",stdin);
    23     //freopen("1.out","w",stdout);
    24     n=read(),m=read(),k=read();
    25     m-=n;k--;
    26     f[1][0]=g[1][0]=1;
    27     for(R int j=1;j<=k;++j)
    28     {
    29         f[1][j]=1;
    30         g[1][j]=(g[1][j-1]+f[1][j])%mod;
    31     }
    32     for(int j=k+1;j<=m;j++)
    33         g[1][j]=g[1][j-1]%mod;
    34     R int cnt=1;
    35     for(R int i=2;i<=n;++i)
    36     {
    37         cnt^=1;
    38         for(R int j=0;j<=m;++j)
    39         {
    40             R int l=max(0,j-k),r=j;
    41             R ll tot=0;
    42             if(l==0)tot=g[cnt^1][r];
    43             else tot=(g[cnt^1][r]-g[cnt^1][l-1]+mod)%mod;
    44             f[cnt][j]=tot%mod;
    45             g[cnt][j]=f[cnt][j]%mod;
    46             if(j)  (g[cnt][j]+=g[cnt][j-1])%=mod;
    47         }
    48     }
    49     printf("%lld
    ",f[cnt][m]%mod);
    50 }
    View Code

    100%算法

    问题转化成:m个物品,放到n个抽屉里,每个至少放一个,最多放k个

    若任何的限制: C(m+n-1,n-1)表示一共有m个物品,分成n组就要用n-1个挡板,把挡板也看成空位,总共m+n-1个空位,选出来n-1个

    若考虑至少放一个:C(m-n+n-1,n-1)先用n个物品给每个抽屉放一个,剩了m-n个物品,再加上n-1个空,剩下的同上

    再考虑k的限制:C(n,i)*C(m-n-i*k+n-1,n-1)表示至少有i个的数量已经超过k(>=k+1)所以先给n个抽屉放一个之后,再给n个放上k个,使之成为k+1个

    就是m-n-i*k,再加上n-1个空

    数组开2e7就行,显然n>m直接return0

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<algorithm>
     6 #define R register
     7 #define ll long long
     8 using namespace std;
     9 inline ll read()
    10 {
    11     ll f=1,x=0;char ch=getchar();
    12     while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    13     while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    14     return f*x;
    15 }
    16 const ll mod=998244353;
    17 const ll maxn=20000005;
    18 ll fac[maxn],inv[maxn],facinv[maxn];
    19 ll n,m,k;
    20 void init()
    21 {
    22     fac[1]=1;
    23     inv[0]=inv[1]=facinv[0]=facinv[1]=1;
    24     for(ll i=2;i<=m+n;i++)
    25     {
    26         fac[i]=fac[i-1]*i*1ll%mod;
    27         inv[i]=(mod-mod/i)*inv[mod%i]%mod;
    28         facinv[i]=facinv[i-1]*inv[i]%mod;
    29     }
    30 }
    31 ll C(ll n,ll m)
    32 {
    33     if(n<m)    return 0;
    34     return 1ll*fac[n]*facinv[n-m]%mod*facinv[m]%mod;
    35 }
    36 int main()
    37 {
    38     n=read(),m=read(),k=read();
    39     if(n>m||n*k<m){puts("0");return 0;}
    40     init();
    41     ll ans=C(m-1,n-1)%mod;
    42     for(ll i=1;i<=n;i++)
    43     {
    44         if(m-n<i*k)break;
    45         ll f=(i&1)?-1:1;
    46         ans=(ans+1ll*f*C(m-i*k-1,n-1)%mod*C(n,i)%mod+mod)%mod;
    47     }
    48     printf("%lld
    ",ans%mod);
    49 }
    View Code

    T2

    对于无环的情况,最优解就是,图中的最长链的长度,,,为什么?

    注意审题:只是炸城市,道路不炸,故某一城市毁了,其他城市的联通性不变,所以最长链上最少要炸的次数就是链长,而其他的路径,当然可以在炸最长链上的每个节点的同时也一起炸,有环的话,tarjan所点成scc,然后拓扑排序,把入度为0的节点放入队列中,枚举其子节点,子节点的答案为,父节点答案加上子节点的scc大小,并且这个点可能使用多次,所以要每次取最大值

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cmath>
      4 #include<cstring>
      5 #include<algorithm>
      6 #include<vector>
      7 #include<queue>
      8 using namespace std;
      9 inline int read()
     10 {
     11     int f=1,x=0;char ch=getchar();
     12     while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
     13     while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
     14     return f*x;
     15 }
     16 const int maxn=1000005;
     17 int n,m;
     18 struct node{
     19     int v,nxt;
     20 }e[2*maxn];int h[maxn],nu;
     21 void add(int x,int y)
     22 {
     23     e[++nu].v=y;
     24     e[nu].nxt=h[x];
     25     h[x]=nu;
     26 }
     27 struct nodc{
     28     int v,nxt;
     29 }ec[maxn*2];int hc[maxn],nuc;
     30 void add_c(int x,int y)
     31 {
     32     ec[++nuc].v=y;
     33     ec[nuc].nxt=hc[x];
     34     hc[x]=nuc;
     35 }
     36 int dfn[maxn],low[maxn],num,top,cnt;
     37 int sta[maxn],ins[maxn],bl[maxn];
     38 vector<int>scc[maxn];
     39 void tarjan(int x)
     40 {
     41     dfn[x]=low[x]=++num;
     42     sta[++top]=x,ins[x]=1;
     43     for(int i=h[x];i;i=e[i].nxt)
     44     {
     45         int y=e[i].v;
     46         if(!dfn[y])
     47         {
     48             tarjan(y);
     49             low[x]=min(low[x],low[y]);
     50             
     51         }
     52         else if(ins[y])
     53             low[x]=min(low[x],dfn[y]);
     54     }
     55     if(dfn[x]==low[x]){
     56         int y;cnt++;
     57         do{
     58             y=sta[top--],ins[y]=0;
     59             scc[cnt].push_back(y);bl[y]=cnt;
     60         }while(y!=x);
     61     }
     62 }
     63 int ind[maxn],ans[maxn];
     64 void topo()
     65 {
     66     queue<int>q;
     67     for(int i=1;i<=cnt;i++)
     68         if(!ind[i])
     69             q.push(i),ans[i]=scc[i].size();
     70     while(q.size())
     71     {//cout<<" ^^^";
     72         int x=q.front();q.pop();
     73         for(int i=hc[x];i;i=ec[i].nxt)
     74         {
     75             int y=ec[i].v;ind[y]--;
     76             if(!ind[y])q.push(y);
     77             int w=scc[y].size();
     78             if(ans[y]<ans[x]+w)ans[y]=ans[x]+w;
     79         }
     80     }
     81 }
     82 int main()
     83 {
     84     //freopen("data","r",stdin);
     85     n=read(),m=read();
     86     for(int i=1;i<=m;i++)
     87     {
     88         int x=read(),y=read();
     89         add(x,y);
     90     }
     91 //    cout<<"^^^";
     92     for(int i=1;i<=n;i++)
     93         if(!dfn[i])
     94             tarjan(i);
     95     for(int x=1;x<=n;x++)
     96     {
     97         for(int i=h[x];i;i=e[i].nxt)
     98         {
     99             int y=e[i].v;
    100             if(bl[x]!=bl[y])
    101                 add_c(bl[x],bl[y]),ind[bl[y]]++;
    102         }
    103     }
    104     topo();
    105     int an=0;
    106     for(int i=1;i<=n;i++)
    107         an=max(ans[i],an);
    108     printf("%d
    ",an);    
    109 }
    View Code
    愿你在迷茫时,记起自己的珍贵。
  • 相关阅读:
    大端小端
    浅谈协程
    boost总结之any
    boost总结之variant
    STL总结之functor
    zabbix设置多个收件人
    zabbix设置发送消息的时间
    zabbix利用微信报警
    Windos无法验证文件数组签名
    zabbix基础安装
  • 原文地址:https://www.cnblogs.com/casun547/p/11329764.html
Copyright © 2011-2022 走看看