zoukankan      html  css  js  c++  java
  • NOIP模拟测试29(A)

    T1:

      题目大意:有一张有向无环图,第$x$次经过边$i$的代价为$a_ix+b_i$,最多经过$c_i$次,起点为1,$s$个点可作为终点,求走$k$次的最小代价。

      我们新建一个汇点,将所有可做为终点的边到汇点连边,那么本题便成为了费用流模型。

      贪心策略为:每次走最短路。

      证明:路径的顺序是可以改变的,设每次走的路径代价是递增的,如果当前不走最短路,那么以后不可能有一条路能将代价追回,所以当前走最短路一定最优。

      但是每次增广代价是不同的,我们只能进行完一次增广之后立即修改边权。

      考虑EK,每次用spfa找一条代价最小的增广路,并更新费用即边权,若当前边是正向边,则将正向边权加$a_i$,反向边权减$a_i$,反之将正向边权减$a_i$,反向边权加$a_i$。正向边初始权值为$a_i+b_i$,由于反向边退流退的是上一层的费用,所以初值应赋为$-b_i$。

      然后增广k次,若流量不能达到k,输出-1。

      spfa复杂度视为$O(NM)$时,时间复杂度$O(NMK)$,但远远达不到。

    Code:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<queue>
     4 using namespace std;
     5 const int N=1010;
     6 const int M=20010;
     7 const int inf=1e9+10;
     8 int n,m,k,s,nm=1,ans=0;
     9 int fi[N],p[N],d[N];
    10 bool v[N];
    11 struct edge{
    12     int v,ne;
    13     int l,a,b;
    14 }e[M+N<<1];
    15 queue<int> q;
    16 int read()
    17 {
    18     int s=0;char c=getchar();
    19     while(c<'0'||c>'9') c=getchar();
    20     while(c>='0'&&c<='9'){
    21         s=(s<<3)+(s<<1)+c-'0';
    22         c=getchar();
    23     }
    24     return s;
    25 }
    26 void add(int x,int y,int z1,int z2,int z3)
    27 {
    28     e[++nm].v=y;e[nm].a=z1;e[nm].b=z1+z2;
    29     e[nm].l=z3;e[nm].ne=fi[x];fi[x]=nm;
    30     e[++nm].v=x;e[nm].a=-z1;e[nm].b=-z2;
    31     e[nm].l=0;e[nm].ne=fi[y];fi[y]=nm;
    32 }
    33 bool spfa()
    34 {
    35     for(int i=1;i<=n;i++){
    36         p[i]=0;d[i]=inf;v[i]=false;
    37     }
    38     while(!q.empty()) q.pop();
    39     d[1]=0;v[1]=true;q.push(1);
    40     while(!q.empty()){
    41         int x=q.front();q.pop();
    42         v[x]=false;
    43         for(int i=fi[x];i!=0;i=e[i].ne){
    44             int y=e[i].v;
    45             if(e[i].l==0) continue;
    46             if(d[y]>d[x]+e[i].b){
    47                 d[y]=d[x]+e[i].b;p[y]=i;
    48                 if(!v[y]){
    49                     v[y]=true;q.push(y);
    50                 }
    51             }
    52         }
    53     }
    54     if(d[n]<inf) return true;
    55     else return false;
    56 }
    57 void update()
    58 {
    59     int x=n;ans+=d[n];
    60     while(x!=1){
    61         int y=p[x];
    62         if((y&1)==0) e[y].b+=e[y].a,e[y^1].b+=e[y^1].a;
    63         else e[y].b-=e[y].a,e[y^1].b-=e[y^1].a;
    64         e[y].l-=1;e[y^1].l+=1;
    65         x=e[y^1].v;
    66     }
    67 }
    68 int main()
    69 {
    70     scanf("%d%d%d%d",&n,&m,&k,&s);
    71     n++;
    72     for(int i=1;i<=s;i++){
    73         int x=read();
    74         add(x,n,0,0,inf);
    75     }
    76     for(int i=1;i<=m;i++){
    77         int x=read(),y=read(),a=read(),b=read(),c=read();
    78         add(x,y,a,b,c);
    79     }
    80     int tot=0;
    81     while(tot<k&&spfa()){
    82         update();tot++;
    83     }
    84     if(tot!=k) printf("-1
    ");
    85     else printf("%d
    ",ans);
    86     return 0;
    87 }
    T1

    T2:

      题目大意:有两数字x和y,以及n数字段,求$[x+1,y]$内至少含有n个数字段的数的个数,对$1e9+7$取模。

      一个数字段可以被包含多次,重复的数字段也要重复计算。

      由区间可以看出此题为数位DP,然后发现字串包含,于是想AC自动机。

      然后这道题变为了AC自动机上的数位DP。

      按照数位DP方法,我们先求出$[1,y]$中合法解的个数,再减去$[1,x]$中合法解的个数,即为答案。

      建出AC自动机,每个点的权值为以该节点为结尾的串的数量,用trie图优化,注意每个节点要继承fail的信息。

      设$dp[i][j][k][0/1]$,代表匹配到第i位,在节点j,匹配了k个子串的方案数,1代表有限制,0代表无限制。

      对于每个数,有无前缀0与其大小无关,于是我们可以带着前缀0进行DP转移。

      设$S$为指向$x$的点集,$w[i]$为节点i的权值,$t[i]$为节点i的类型,$a$为较大的边界,则:

        $dp[i][x][j][0]= sum _{y in S} dp[i-1][y][j-w[x]][0]+[t[x]<a[i]]* sum _{y in S} dp[i-1][y][j-w[x]][1]$

        $dp[i][x][j][1]=[t[x]==a[i]]* sum _{y in S} dp[i-1][y][j-w[x]][1]$

      由于没有考虑前缀0影响,统计答案时只累加长度等于原串的答案即可。

      时间复杂度$O(NSK)$,$S$为子串总长。

    Code:

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<string>
      4 #include<cstring>
      5 #include<queue>
      6 #define LL long long
      7 using namespace std;
      8 const LL mod=1e9+7;
      9 int n,k,rt=0,cnt=0;
     10 string s;
     11 int a[2][510];
     12 LL dp[510][210][20][4];
     13 bool v[510][210][20][4];
     14 struct trie{
     15     int ch[10],fail;
     16     int e;
     17 }t[210];
     18 queue<int> q,q1,q2,q3,q4;
     19 void insert()
     20 {
     21     int now=rt;
     22     for(int i=0;i<s.size();i++){
     23         int x=s[i]-'0';
     24         if(t[now].ch[x]==0)
     25             t[now].ch[x]=++cnt;
     26         now=t[now].ch[x];
     27     }
     28     t[now].e++;
     29 }
     30 void build()
     31 {
     32     for(int i=0;i<=9;i++){
     33         if(t[rt].ch[i]!=0) q.push(t[rt].ch[i]);
     34     }
     35     while(!q.empty()){
     36         int x=q.front();q.pop();
     37         for(int i=0;i<=9;i++){
     38             if(t[x].ch[i]!=0){
     39                 t[t[x].ch[i]].fail=t[t[x].fail].ch[i];
     40                 t[t[x].ch[i]].e+=t[t[t[x].fail].ch[i]].e;
     41                 q.push(t[x].ch[i]);
     42             }
     43             else t[x].ch[i]=t[t[x].fail].ch[i];
     44         }
     45     }
     46 }
     47 LL work(int id)
     48 {    
     49     memset(dp,0,sizeof(dp));
     50     memset(v,false,sizeof(v));
     51     while(!q1.empty()){
     52         q1.pop();q2.pop();q3.pop();q4.pop();
     53     }
     54     dp[0][rt][0][3]=1;v[0][rt][0][3]=true;
     55     q1.push(0);q2.push(rt);q3.push(0);q4.push(3);
     56     while(!q1.empty()){
     57         int x=q1.front(),y=q2.front(),z=q3.front(),op=q4.front();
     58         v[x][y][z][op]=false;
     59         q1.pop();q2.pop();q3.pop();q4.pop();
     60         if(x==a[id][0]) break;
     61         for(int i=0;i<=((op&1)==1?a[id][x+1]:9);i++){
     62             int yy=t[y].ch[i];int zz=z+t[yy].e;
     63             if(zz>k) zz=k;
     64             if((op&2)==2&&i==0){
     65                 if((op&1)==1&&i==a[id][x+1]){
     66                     dp[x+1][yy][zz][3]=(dp[x+1][yy][zz][3]+dp[x][y][z][op])%mod;
     67                     if(!v[x+1][yy][zz][3]){
     68                         q1.push(x+1);q2.push(yy);q3.push(zz);q4.push(3);
     69                         v[x+1][yy][zz][3]=true;
     70                     }
     71                 }
     72                 else{
     73                     dp[x+1][yy][zz][2]=(dp[x+1][yy][zz][2]+dp[x][y][z][op])%mod;
     74                     if(!v[x+1][yy][zz][2]){
     75                         q1.push(x+1);q2.push(yy);q3.push(zz);q4.push(2);
     76                         v[x+1][yy][zz][2]=true;
     77                     }
     78                 }
     79             }
     80             else{
     81                 if((op&1)==1&&i==a[id][x+1]){
     82                     dp[x+1][yy][zz][1]=(dp[x+1][yy][zz][1]+dp[x][y][z][op])%mod;
     83                     if(!v[x+1][yy][zz][1]){
     84                         q1.push(x+1);q2.push(yy);q3.push(zz);q4.push(1);
     85                         v[x+1][yy][zz][1]=true;
     86                     }
     87                 }
     88                 else{
     89                     dp[x+1][yy][zz][0]=(dp[x+1][yy][zz][0]+dp[x][y][z][op])%mod;
     90                     if(!v[x+1][yy][zz][0]){
     91                         q1.push(x+1);q2.push(yy);q3.push(zz);q4.push(0);
     92                         v[x+1][yy][zz][0]=true;
     93                     }
     94                 }
     95             }
     96         }
     97     }
     98     LL ans=0;
     99     for(int j=0;j<=cnt;j++){
    100         ans=(ans+dp[a[id][0]][j][k][0])%mod;
    101         ans=(ans+dp[a[id][0]][j][k][1])%mod;
    102     }
    103     return ans;
    104 }
    105 int main()
    106 {
    107     scanf("%d%d",&n,&k);
    108     cin>>s;a[0][0]=s.size();
    109     for(int i=1;i<=a[0][0];i++) a[0][i]=s[i-1]-'0';
    110     cin>>s;a[1][0]=s.size();
    111     for(int i=1;i<=a[1][0];i++) a[1][i]=s[i-1]-'0';
    112     for(int i=1;i<=n;i++){
    113         cin>>s;insert();
    114     }
    115     build();
    116     LL ans=work(1);
    117     ans-=work(0);
    118     ans=(ans%mod+mod)%mod;
    119     printf("%lld
    ",ans);
    120     return 0;
    121 }
    T2

     

  • 相关阅读:
    获取网络动态flash下载地址工具mark HA
    mac 下windows系统修改快捷键 HA
    CABasicAnimation HA
    喷墨和激光打印的不同点 HA
    HTML iphone HA
    html5 HA
    CastleMonoRail配置[webConfig]
    什么是MonoRail?[基础知识讲解]
    javascript常用函数
    CastleGlobalApplication.cs工程起始加载
  • 原文地址:https://www.cnblogs.com/hz-Rockstar/p/11397040.html
Copyright © 2011-2022 走看看