zoukankan      html  css  js  c++  java
  • 【61测试】【dp】【二分】【前缀和】【树剖】

    不要问我为什么昨天考的今天才贴解题报告。。

    第一题:

      给定3个字符串,求它们的最长公共子序列。

    解:

      考试时知道肯定是LCS的二维再加一维,用三维,可天堂有路你不走,地狱无门你偏来。。。灵机一动想出来一个方法:先记下前两个的最长公共子序列(可能有多个),然后再一一与第三个字符串比较,找出三者的最长公共子序列。然后就GG了。想不通,思路应该是对的啊。所以又留了一道题来想。

      然后三维的状态转移很好写。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<map>
     6 #define maxn 125
     7 using namespace std;
     8 char a[maxn],b[maxn],c[maxn];
     9 int n,f[maxn][maxn][maxn];
    10 int main()
    11 {
    12     freopen("subq.in","r",stdin);
    13     freopen("subq.out","w",stdout);
    14     cin>>n;
    15     scanf("%s%s%s",a+1,b+1,c+1);
    16     for (int i=1;i<=n;i++)
    17       for (int j=1;j<=n;j++)
    18         for (int k=1;k<=n;k++)
    19         {
    20             f[i][j][k]=max(f[i-1][j][k],max(f[i][j-1][k],f[i][j][k-1]));
    21             if (a[i]==b[j]&&b[j]==c[k])
    22               f[i][j][k]=f[i-1][j-1][k-1]+1;
    23         }
    24     cout<<f[n][n][n];
    25     return 0;
    26 }

    不要后悔。。。


    第二题:

      定义两个素数是连续的当且仅当这两个素数之间不存在其他的素数(如 7,11 ,(23,29)。给定N,K,在不超过N的正整数中求能够分解为K个连续的素数的和的最大的那个是多少。

    解:

      先开始连题都读错了,想着完了我肯定不会,这是唯一分解定理啊,数论没看过啊。然后再定睛几看,额,只是一个和而已好吗。下次要先把题读清楚。

      然后就是先求出10^6以内的素数,然后 前缀和+二分答案。哦,因为一个二分模板的问题,哎。贴一个二分模板:

    int l=1 , r=n+1;
        while(l<r) // the minimum line above P(x0,y0)
        {
            int m = (l+r)>>1;
            if(check(m)) r = m;//在下面;
            else l = m + 1;
        }
        return l-1;

    代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define maxn 1000005
     6 #define ll long long
     7 using namespace std;
     8 int t,n[2005],k[2005],ma,su[maxn],idx;
     9 ll he[maxn];
    10 bool zhi[maxn];
    11 void get_zhi(int x)
    12 {
    13     memset(zhi,true,sizeof(zhi));
    14     for (int i=2;i*i<=x;i++)
    15     if (zhi[i]){
    16         for(int j=i*i;j<=x;j+=i)
    17         if (zhi[j]){
    18             zhi[j]=false;
    19         }
    20     }
    21     zhi[1]=false;
    22     for (int i=2;i<=x;i++)
    23     if (zhi[i]) {
    24         //su[++idx]=i;
    25         ++idx;
    26         he[idx]=(ll)he[idx-1]+i;
    27     }
    28 }
    29 void work(int x,int y)
    30 {
    31     int l=y,r=idx;//l
    32     ll ans=-1;
    33     while (l<=r){
    34         int mid=(l+r)>>1;
    35         ll an=he[mid]-he[max(0,mid-y)];
    36         if (an<=x){l=mid+1;ans=an;}
    37         else r=mid-1;
    38     }
    39     printf("%I64d
    ",ans);
    40     /*if (he[l]-he[l-y]>x) {
    41         l--;ans=he[l]-he[l-y];
    42     }
    43     //if (l+1>y&&he[l]-he[l-y]>x) 
    44     else if (ans!=-1&&he[l]-he[l-y]>x&&l-1<=y) ans=-1;
    45     if (l-y<0) ans=-1;*/
    46     //l+=1;
    47     /*for (int i=l;i>=y;i--)//****
    48     {
    49         if (i>idx) continue;
    50         if (he[i]-he[i-y]<=1) {//****
    51             printf("-1
    ");
    52             return ;
    53         }
    54         else if (he[i]-he[i-y]<=x) {
    55             printf("%I64d
    ",he[i]-he[i-y]);
    56             return ;
    57         }
    58     } 
    59     printf("-1
    ");*/
    60 }
    61 int main()
    62 {
    63     freopen("dun.in","r",stdin);
    64     freopen("dun.out","w",stdout);
    65     cin>>t;
    66     for (int i=1;i<=t;i++)
    67     {
    68         scanf("%d%d",&n[i],&k[i]);
    69         if (n[i]>ma) ma=n[i];
    70     }    
    71     get_zhi(ma);
    72     for (int i=1;i<=t;i++)
    73         work(n[i],k[i]);
    74     return 0;
    75 }

    第三题

      有一个村庄在闹饥荒,善良而土豪的YGH决定给他们发放救济粮,该村庄有 n 户人家,每两户人家之间只有一条路可以互相到达,即这些人家之间形成一棵树。现在 YGH 会以这样的形式给他们发放粮食,选择两户人家,然后对这两个户人家路径上的所有人家都发放一袋种类为 w 的救济粮。在完成一系列发放任务后,YGH 想知道每一户人家收到的粮食中数量最多的是哪一种。

    解:

      40%:暴力。注意dfs的返回如果没有加判断,那么idx一直往下减就会下标超界。。然后就不知道哪里的值会被改了。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define maxn 1005
     6 using namespace std;
     7 int n,q,road[maxn],idx;
     8 int tot,he[maxn],ne[maxn*2],to[maxn*2];
     9 bool vis[maxn],can=false;
    10 struct pp{
    11     int sum;
    12     int w[maxn],num[maxn];
    13 };
    14 pp house[maxn];
    15 void add(int a,int b)
    16 {
    17     tot++;to[tot]=b;ne[tot]=he[a];he[a]=tot;
    18 }
    19 void update(int x,int y,int ad)
    20 {
    21     road[++idx]=x;
    22     vis[x]=true;
    23     if (x==y){
    24         while (idx)
    25         {
    26             int s=road[idx];
    27             bool yes=false;
    28             for (int i=1;i<=house[s].sum;i++)
    29               if (house[s].w[i]==ad){
    30                   house[s].num[i]++;
    31                   yes=true;
    32                   break;
    33               }
    34             if(!yes){
    35                 house[s].sum++;
    36                 house[s].w[house[s].sum]=ad;
    37                 house[s].num[house[s].sum]++;
    38             }
    39             idx--;
    40         }
    41         can=true;
    42         return ;
    43     }
    44     for (int i=he[x];i;i=ne[i])
    45     if (!vis[to[i]]){
    46         vis[to[i]]=true;
    47         update(to[i],y,ad);
    48         if (can) return ;//回溯不加判断会下标超界 
    49         vis[to[i]]=false;
    50         idx--;
    51     }
    52 }
    53 int main()
    54 {
    55     freopen("rice.in","r",stdin);
    56     freopen("rice.out","w",stdout);
    57     cin>>n>>q;
    58     for (int i=1;i<n;i++)
    59     {
    60         int x,y;
    61         scanf("%d%d",&x,&y);
    62         add(x,y);
    63         add(y,x);
    64     }
    65      for (int i=1;i<=q;i++)
    66     {
    67         int x,y,z;idx=0;can=false;
    68         memset(road,0,sizeof(road));
    69         memset(vis,0,sizeof(vis));
    70         scanf("%d%d%d",&x,&y,&z);
    71         update(x,y,z);
    72     }
    73     for (int i=1;i<=n;i++)
    74     {
    75         int mx=0,cur=12345678;
    76         for (int j=1;j<=house[i].sum;j++)
    77         {
    78             if (house[i].num[j]>mx) 
    79                 mx=house[i].num[j];
    80         }
    81         for (int j=1;j<=house[i].sum;j++)
    82         if (house[i].num[j]==mx) {
    83             if (house[i].w[j]<cur) cur=house[i].w[j];
    84         }
    85         if (cur==12345678) cout<<"0"<<endl;
    86         else printf("%d
    ",cur);
    87     }
    88     return 0;
    89 }
    90 //30 min

      100%:树剖。先挖坑。

  • 相关阅读:
    收藏夹
    获取某个元素在页面上的偏移量
    React多行文本溢出处理(仅针对纯文本)
    react
    CDN初学搭建(ats)
    linux查看cpu、内存、版本信息
    MySQL5.6版本性能调优my.cnf详解
    How to install cacti on centos 6
    win10安装.net3.5 报错解决
    CentOS6.5安装Cacti统计图乱码解决
  • 原文地址:https://www.cnblogs.com/lx0319/p/6052361.html
Copyright © 2011-2022 走看看