zoukankan      html  css  js  c++  java
  • ASC2 做题记录

    A.

    预处理出每个状态的转移(t(u,c)),然后(dp(i,j))表示长度为(i)在DFA上状态为(j)DP即可

    答案需要高精度

      1 #include<bits/stdc++.h>
      2 #define MAXL 205
      3 using namespace std;
      4 const int power = 4;
      5 const int base = 10000;
      6 struct num
      7 {
      8     int l;
      9     int a[MAXL];
     10     num() { memset(a, 0, sizeof (a));l = 0;}
     11     num(const char *s)
     12     {
     13         memset(a, 0, sizeof (a));
     14         int len = strlen(s);
     15         l = (len + power - 1) / power;
     16         for (int i = 0, t = 0, j = len - 1, w; i < len; w *= 10, ++i, --j)
     17         {
     18             if (i % power == 0) {w = 1, ++t;}
     19             a[t] += w * (s[j] - '0');
     20         }
     21     }
     22     friend ostream & operator<<(ostream &o, num &n)
     23     {
     24         o << n.a[n.l];
     25         for (int i = n.l - 1; i > 0; --i)
     26         {
     27             if(n.a[i]<10)o<<"000";
     28             else if(n.a[i]<100)o<<"00";
     29             else if(n.a[i]<1000)o<<"0";
     30             o<<n.a[i];
     31         }
     32         return o;
     33     }
     34 };
     35 num operator+(const num &p, const num &q) {
     36     num c;
     37     c.l = max(p.l, q.l);
     38     for (int i = 1; i <= c.l; ++i) {
     39         c.a[i] += p.a[i] + q.a[i];
     40         c.a[i + 1] += c.a[i] / base;
     41         c.a[i] %= base;
     42     }
     43     if (c.a[c.l + 1]) ++c.l;
     44     return c;
     45 }
     46 char sig[30];
     47 int m,n,len;
     48 int s,L;
     49 bool is[1005];
     50 bool vis[1005];
     51 int ph[1005][26],ka[1005][26],t[1005][26];
     52 num dp[65][1005];
     53 int main()
     54 {
     55     freopen("dfa.in","r",stdin);
     56     freopen("dfa.out","w",stdout);
     57     scanf("%s",sig);
     58     m=strlen(sig);
     59     scanf("%d",&n);
     60     scanf("%d%d",&s,&L);
     61     for(int i=1;i<=L;++i)
     62     {
     63         int x;
     64         scanf("%d",&x);
     65         is[x]=1;
     66     }
     67     for(int i=1;i<=n;++i)
     68         for(int j=0;j<m;++j)scanf("%d",&ph[i][j]);
     69     for(int i=1;i<=n;++i)
     70         for(int j=0;j<m;++j)scanf("%d",&ka[i][j]);
     71     for(int i=1;i<=n;++i)
     72         for(int j=0;j<m;++j)
     73         {
     74             memset(vis,0,sizeof(vis));
     75             int u=i;
     76             while(ka[u][j])
     77             {
     78                 if(vis[u])break;
     79                 vis[u]=1;
     80                 u=ph[u][j];
     81             }
     82             if(vis[u])t[i][j]=0;
     83             else t[i][j]=ph[u][j];
     84         }
     85     scanf("%d",&len);
     86     dp[0][s]=num("1");
     87     for(int i=0;i<len;++i)
     88         for(int j=1;j<=n;++j)
     89         {
     90             for(int k=0;k<26;++k)if(t[j][k])
     91             {
     92                 dp[i+1][t[j][k]]=dp[i+1][t[j][k]]+dp[i][j]; 
     93             }
     94         }
     95     num ans=num("0");
     96     for(int i=1;i<=n;++i)
     97     {
     98         if(is[i])ans=ans+dp[len][i];
     99     }
    100     cout<<ans<<endl;
    101 }
    View Code

    B.

    多柱汉诺塔

    考虑一个n个盘子m个柱子的情况

    枚举一个x表示把盘子分成两部分x和n-x,我们的策略是把x个盘子通过m个柱子从s移到pos(某个能放下这x个盘子的位置),然后剩下n-x个盘子从s直接移动到t,然后再把原来的x个盘子从pos移动到t

    DP式子为(dp(i,j)=min(2*dp(i,k)+dp(i-1,j-k)))

    方案按上面策略输出

     1 #include<bits/stdc++.h>
     2 #define maxn 70
     3 using namespace std;
     4 typedef unsigned long long ll;
     5 int n,m;
     6 ll dp[maxn][maxn];
     7 int pre[maxn][maxn];
     8 int stk[maxn][maxn];
     9 int top[maxn];
    10 void print(int s,int t,int mm,int nn)
    11 {
    12     if(nn==1)
    13     {
    14         if(top[t])
    15         {
    16             printf("move %d from %d to %d atop %d
    ",stk[s][top[s]],s,t,stk[t][top[t]]);
    17         }
    18         else
    19         {
    20             printf("move %d from %d to %d
    ",stk[s][top[s]],s,t);
    21         }
    22         int x=stk[s][top[s]];
    23         --top[s];
    24         stk[t][++top[t]]=x;
    25         return;
    26     }
    27     int k=pre[mm][nn];
    28     int pos=0;
    29     for(int i=1;i<=m;++i)if(i!=s&&i!=t)
    30     {
    31         if(top[i]&&stk[i][top[i]]<stk[s][top[s]-k+1])continue;
    32         pos=i;
    33     }
    34     print(s,pos,mm,k);
    35     print(s,t,mm-1,nn-k);
    36     print(pos,t,mm,k);
    37 }
    38 int main()
    39 {
    40     freopen("hanoi.in","r",stdin);
    41     freopen("hanoi.out","w",stdout);
    42     scanf("%d%d",&n,&m);
    43     dp[3][1]=1;
    44     for(int i=2;i<=64;++i)
    45     {
    46         dp[3][i]=dp[3][i-1]*2+1;
    47         pre[3][i]=i-1;
    48     }
    49     for(int j=4;j<=m;++j)
    50     {
    51         dp[j][1]=1;
    52         for(int i=2;i<=n;++i)
    53         {
    54             dp[j][i]=dp[3][64];
    55             for(int k=1;k<i;++k)
    56             {
    57                 if(dp[j][i]>dp[j][k]*2+dp[j-1][i-k])
    58                 {
    59                     dp[j][i]=dp[j][k]*2+dp[j-1][i-k];
    60                     pre[j][i]=k;
    61                 }
    62             }
    63         }
    64     }
    65     printf("%d
    ",(int)dp[m][n]);
    66     for(int i=1;i<=m;++i)top[i]=0;
    67     for(int i=1;i<=n;++i)stk[1][++top[1]]=n-i+1;
    68     print(1,m,m,n);
    69 }
    View Code

    C.

    用堆模拟huffman建树

     1 #include<bits/stdc++.h>
     2 #define maxn 500005
     3 using namespace std;
     4 typedef long long ll;
     5 int n;
     6 void read(int &x)
     7 {
     8     x=0;
     9     char ch=getchar();
    10     while(ch<'0'||ch>'9')ch=getchar();
    11     while('0'<=ch&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    12 }
    13 int main()
    14 {
    15     freopen("huffman.in","r",stdin);
    16     freopen("huffman.out","w",stdout);
    17     scanf("%d",&n);
    18     priority_queue<ll> q;
    19     for(int i=1;i<=n;++i)
    20     {
    21         int x;
    22         read(x); 
    23         q.push(-x);
    24     }
    25     ll ans=0;
    26     while(!q.empty())
    27     {
    28         ll u=-q.top();q.pop();
    29         if(q.empty())break;
    30         ll v=-q.top();q.pop();
    31         ans+=u+v;
    32         q.push(-(u+v));
    33     }
    34     printf("%lld
    ",ans);
    35 }
    View Code

    D.

    E.

    (dp(i,j))表示第(i)个数对应第(j)行,然后枚举这行里面选哪个转移,记录方案

     1 #include<bits/stdc++.h>
     2 #define maxn 1005
     3 using namespace std;
     4 const int inf = 1000000000;
     5 int n,m,s;
     6 int x[maxn];
     7 int val[130][130];
     8 int dp[maxn][130],pre[maxn][130],cho[maxn][130];
     9 void print(int i,int j)
    10 {
    11     if(!i)return;
    12     print(i-1,pre[i][j]);
    13     printf("%d ",cho[i][j]);
    14 }
    15 int main()
    16 {
    17     freopen("quant.in","r",stdin);
    18     freopen("quant.out","w",stdout);
    19     scanf("%d",&n);
    20     for(int i=1;i<=n;++i)scanf("%d",&x[i]);
    21     scanf("%d%d",&m,&s);
    22     for(int i=0;i<m;++i)
    23         for(int j=0;j<s;++j)scanf("%d",&val[i][j]);
    24     for(int i=0;i<=n;++i)
    25         for(int j=0;j<m;++j)dp[i][j]=inf;
    26     dp[0][0]=0;
    27     for(int i=1;i<=n;++i)
    28     {
    29         for(int j=0;j<m;++j)
    30         {
    31             for(int k=0;k<s;++k)
    32             {
    33                 if(dp[i-1][j]+abs(x[i]-val[j][k])<dp[i][k&(m-1)])
    34                 {
    35                     dp[i][k&(m-1)]=dp[i-1][j]+abs(x[i]-val[j][k]);
    36                     pre[i][k&(m-1)]=j;cho[i][k&(m-1)]=k;
    37                 }
    38             }
    39         }
    40     }
    41     int ans=inf;
    42     for(int j=0;j<m;++j)ans=min(ans,dp[n][j]);
    43     printf("%d
    ",ans);
    44     for(int j=0;j<m;++j)if(ans==dp[n][j])
    45     {
    46         print(n,j);
    47         break;
    48     }
    49 }
    View Code

    F.

    对于一条树边必然是减,非树边必然是加

    那么考虑树边x和非树边y

    (C(x)-Delta(x) leq C(y)+Delta(y))

    整理得

    (C(x)-C(y) leq Delta(x)+Delta(y))

    目标是最小(Delta(i))之和

    关系式可以对应KM中顶标和大于等于边权,目标可以对应KM中最小顶标和的性质

    那么建立二部图跑KM即可

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 typedef long long ll;
      4 const int maxn = 405;
      5 struct KM{
      6     const ll inf = 1ll << 60;
      7     ll G[maxn][maxn], hl[maxn], hr[maxn], dt[maxn];
      8     int fl[maxn], fr[maxn], vl[maxn], vr[maxn], pre[maxn], q[maxn], ql, qr, n;
      9     void init(int nl, int nr){
     10         n = max(nl, nr);
     11         for(int i = 1; i <= n; ++i)
     12             for(int j = 1; j <= n; ++j) G[i][j] = 0;
     13     }
     14     void add(int u, int v, ll w){
     15         G[u][v] = max(G[u][v], w);
     16     }
     17     int check(int i){
     18         if(vl[i] = 1, fl[i] != -1) return vr[q[qr++] = fl[i]] = 1;
     19         while(i != -1) swap(i, fr[fl[i] = pre[i]]);
     20         return 0;
     21     }
     22     void bfs(int s){
     23         for(int i = 1; i <= n; ++i) vl[i] = vr[i] = 0, dt[i] = inf;
     24         for(vr[q[ql = 0] = s] = qr = 1;;){
     25             for(ll d; ql < qr;){
     26                 for(int i = 1, j = q[ql++]; i <= n; ++i){
     27                     if(!vl[i] && dt[i] >= (d = hl[i] + hr[j] - G[i][j])){
     28                         if(pre[i] = j, d) dt[i] = d;
     29                         else if(!check(i)) return;
     30                     }
     31                 }
     32             }
     33             ll d = inf;
     34             for(int i = 1; i <= n; ++i){
     35                 if(!vl[i] && d > dt[i]) d = dt[i];
     36             }
     37             for(int i = 1; i <= n; ++i){
     38                 if(vl[i]) hl[i] += d;
     39                 else dt[i] -= d;
     40                 if(vr[i]) hr[i] -= d;
     41             }
     42             for(int i = 1; i <= n; ++i){
     43                 if(!vl[i] && !dt[i] && !check(i)) return;
     44             }
     45         }
     46     }
     47     ll solve(){
     48         for(int i = 1; i <= n; ++i) fl[i] = fr[i] = -1, hr[i] = 0;
     49         for(int i = 1; i <= n; ++i)
     50         {
     51             hr[i] = 0;
     52             for(int j = 1; j <= n; ++j) hr[i] = max(hr[i], G[j][i]);
     53         }
     54         for(int i = 1; i <= n; ++i) bfs(i);
     55         ll ret = 0;
     56         for(int i = 1; i <= n; ++i) if(G[i][fl[i]]) ret += G[i][fl[i]]; else fl[i] = 0;
     57         return ret;
     58     }
     59 }km;
     60 int n,m;
     61 int C[maxn];
     62 int stk[maxn],top;
     63 vector<int> tmp;
     64 vector< pair<int,int> > g[maxn];
     65 void dfs(int u,int f,int rt,int t)
     66 {
     67     if(u==t)
     68     {
     69         for(int i=1;i<=top;++i)tmp.push_back(stk[i]);
     70     }
     71     for(auto p:g[u])if(p.first!=f)
     72     {
     73         stk[++top]=p.second;
     74         dfs(p.first,u,rt,t);
     75         --top;
     76     }
     77 }
     78 int main()
     79 {
     80     freopen("roads.in","r",stdin);
     81     freopen("roads.out","w",stdout);
     82     scanf("%d%d",&n,&m);
     83     for(int i=1;i<n;++i)
     84     {
     85         int u,v,w;
     86         scanf("%d%d%d",&u,&v,&w);
     87         g[u].push_back(make_pair(v,i));
     88         g[v].push_back(make_pair(u,i));
     89         C[i]=w;
     90     }
     91     km.init(n-1,m-n+1);
     92     for(int i=n;i<=m;++i)
     93     {
     94         int u,v,w;
     95         scanf("%d%d%d",&u,&v,&w);
     96         C[i]=w;
     97         tmp.clear();
     98         top=0;
     99         dfs(u,0,u,v);
    100         for(int x:tmp)
    101         {
    102             km.add(x,i-n+1,C[x]-C[i]);
    103         }
    104     }
    105     km.solve();
    106     for(int i=1;i<n;++i)C[i]-=km.hl[i];
    107     for(int i=n;i<=m;++i)C[i]+=km.hr[i-n+1];
    108     for(int i=1;i<=m;++i)printf("%d
    ",C[i]);
    109 }
    View Code

    G.

    考虑尽量平均分到下取整,然后每次找增量最优的

     1 #include<bits/stdc++.h>
     2 #define maxn 1005
     3 using namespace std;
     4 typedef long long ll;
     5 int n;
     6 ll M,Y,X[maxn],T;
     7 ll K[maxn];
     8 int main()
     9 {
    10     freopen("input.txt","r",stdin);
    11     freopen("output.txt","w",stdout);
    12     scanf("%d%lld%lld",&n,&M,&Y);
    13     T=M;
    14     for(int i=1;i<=n;++i)
    15     {
    16         scanf("%lld",&X[i]);
    17         K[i]=X[i]*M/Y;
    18         T-=K[i];
    19     }
    20     priority_queue< pair<ll,int> > q;
    21     for(int i=1;i<=n;++i)
    22     {
    23         ll c=abs(X[i]*M-K[i]*Y)-abs(X[i]*M-(K[i]+1)*Y);
    24         q.push(make_pair(c,i));
    25     }
    26     while(T--)
    27     {
    28         int u=q.top().second;q.pop();
    29         K[u]++;
    30     }
    31     for(int i=1;i<=n;++i)printf("%lld%c",K[i],(i==n)?'
    ':' ');
    32 }
    View Code

    H.

  • 相关阅读:
    用python3实现linux的sed功能
    查找列表中指定的所有元素的位置
    Django分页
    python3中字典的copy
    Python中is和==的区别的
    python3的文件读写模式
    使用python3简单完成购物过程
    python3中str的函数
    第一篇
    《笑傲江湖》传剑摘录 有感而发
  • 原文地址:https://www.cnblogs.com/uuzlove/p/14128378.html
Copyright © 2011-2022 走看看