week18

#740. 最长公共子序列

 附加文件 统计

给出从 1 到 n的两个排列 P1和 P2,求它们的最长公共子序列。

输入格式

第一行是一个正整数 n。

接下来两行,每行为 n个数,为自然数 1,2,…,n的一个排列。

输出格式

一个数,即最长公共子序列的长度。

数据范围

1≤n≤10^5

输入样例

5 
3 2 1 4 5
2 1 3 4 5

输出样例

4
#include<bits/stdc++.h>
using namespace std;
int N,b[100005],lcs[100005],res,a[100005];
int main()
{
    scanf("%d",&N);
    for(int i=1;i<=N;i++)
    {
        scanf("%d",&a[i]);
    }
    for(int i=1;i<=N;i++)
    {
        int t;
        scanf("%d",&t);
        b[t]=i;
    }
    for(int i=1;i<=N;i++)a[i]=b[a[i]];
    res=0;
    for(int i=1;i<=N;i++)
    {
        if(a[i]>lcs[res])
        {
            res++;
            lcs[res]=a[i];
        }
        else
        {
            int p=lower_bound(lcs+1,lcs+1+res,a[i])-lcs;
            lcs[p]=a[i];
        }
    }
    cout<<res<<endl;
}

 

#742. 喵喵序列

 附加文件 统计

题目描述

给定一个含有 n 个整数的序列 a1,a2,…an,三个数 i,j,k 是可爱的当且仅当 i<j<k 且 ai<aj<ak。

请你求出有多少组 i,j,k 是可爱的。

输入格式

第 1行一个整数 n 表示序列元素个数。

第 2 行 n 个整数分别表示 a1,a2,…an。

输出格式

一行一个整数,表示所求数量。

样例输入

5
1 2 2 3 4

样例输出

7

样例说明

满足条件的有:(1,2,3),(1,2,4),(1,2,3),(1,2,4),(1,3,4),(2,3,4),(2,3,4),共 7 个。

数据范围

对于全部数据,有 1≤n≤3×10^4,0≤ai<2^63。

#include<bits/stdc++.h>
using namespace std;
long long N,a[30004],ans;
struct nn
{
    long long c1,c2,v;
};
set<long long>nums;
nn f[30004];
int main()
{
    scanf("%d",&N);
    for(int i=1;i<=N;i++)
    {
        scanf("%lld",&a[i]);
        nums.insert(a[i]);
    }
    int tt=1;
    for(auto it=nums.begin();it!=nums.end();it++)
    {
        f[tt].v=*it;
        tt++;
    }
    tt--;
    for(int i=1;i<=N;i++)
    {
        long long t=0,t1=0;
        for(int j=1;j<=tt;j++)
        {
            if(f[j].v==a[i])
            {
                f[j].c1++;
                f[j].c2+=t;
                ans+=t1;
                break;
            }
            else
            {
                t+=f[j].c1;
                t1+=f[j].c2;
            }
        }
    }
    cout<<ans<<endl;
}

 

#743. 漂亮数

 附加文件 统计

有一个长度为 n 的数字 X,由 n 位数字组成,即 a1,a2,...an,它们按从左到右的顺序组成一个十进制的数。

并且,你将得到一个数 k,需要你构造出一个最小的数 Y,对于每一位 i(1≤i≤m−k), 满足 bi=bi+k,并且X≤Y。

输入描述

第一行给出两个数 n,k 其中 (2≤n≤200000,1≤k<n)。

第二行给出 X:a1,a2,...an。

输出描述

第一行给出Y的长度 m。

输出最小的满足条件的数 Y:b1,b2,...bm。

输入样例

3 2
353

输出样例

3
353
#include<bits/stdc++.h>
using namespace std;
int main() {
    int n, k;
    cin >> n >> k;
    vector<int>x(n), y(k);
    string s;
    cin >> s;
    bool flag = true;
    for (int i = 0; i < n; i++)
    {
        x[i] = s[i] - '0';
        if (i < k)y[i] = x[i];
    }
    flag = false;
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < k; j++)
        {
            if (y[j] < x[i + j])
            {
                int ans = k - 1;
                while (y[ans] == 9)ans--;
                y[ans]++;
                for (int l = ans + 1; l < k; l++)y[l] = 0;
                flag = true;
                break;
            }
            else if (y[j] > x[i + j])
            {
                flag = true;
                break;
            }
        }
        i += k - 1;
        if (flag)break;
    }
    cout << n << endl;
    for (int i = 0; i < n; i++)
    {
        cout << y[i % k];
    }
    return 0;
}

 

#745. 真假字符串

 附加文件 统计

给定两个长度相等的字符串 S1,S2, 问能否找出一个字符串 S, 使得 S 只删除一个字符可以得到 S1, 并且 S只删除一个字符也可以得到 S2 (可以是不同位置的字符)。

输入格式

输入第一行给出字符串 S1, 第二行给出字符串 S2, 两个字符串的长度 1≤len≤300000。

输出格式

如果能找到满足条件的字符串 S, 输出 1, 否则输出 0。

样例输入

abacaa
aacaba

样例输出

1

样例解释

abacaba 删除第二个字符 b 可以得到字符串 S1, 并且删除第一个字符 b 可以得到字符串 S2。

#include<bits/stdc++.h>
using namespace std;
string x,y;
int main()
{
    cin>>x>>y;
    int len=x.size(),m,n;
    for(int i=0;i<len;i++)
    {
        if(x[i]!=y[i])
        {
            m=i;
        }
    }
    for(int i=len-1;i>=0;i--)
    {
        if(x[i]!=y[i])
        {
            n=i;
        }
    }
    string x1=x,x2=x,y1=y,y2=y;
    x1.erase(m,1);
    y1.erase(n,1);
    x2.erase(n,1);
    y2.erase(m,1);
    if(x1==y1||x2==y2)cout<<1<<endl;
    else cout<<0<<endl;
}

 

#801. 走不出的迷宫

 附加文件 统计

​ 有一个 H行 W 列的迷宫(行号从上到下是 1−H,列号从左到右是 1−W),现在有一个由 . 和 # 组成的 H 行 W 列的矩阵表示这个迷宫的构造,. 代表可以通过的空地,# 代表不能通过的墙。

​ 现在有个人从 起点 (1,1) 开始走,他每一步只能往右走一格或者往下走一格,并且他不能跨越迷宫的边界。他会一直走,直到没有可以走的路时停下来。

​ 请问这个人最多可以经过多少个格子?

输入格式

​ 第一行两个整数 H,W,表示迷宫有 H 行 W 列。

​ 接下来一个 H 行 W列的由 . 和 # 组成的矩阵,表示迷宫的构造。

​ 注意:保证 (1,1)的位置一定是 .

输出格式

​ 一个整数,表示最多步数。

样例输入1

3 4
.#..
..#.
..##

样例输出1

4

样例输入2

1 1
.

样例输出2

1

样例输入3

5 5
.....
.....
.....
.....
.....

样例输出3

9

数据规模

​ 对于全部数据保证 1≤H,W≤100

#include<bits/stdc++.h>
using namespace std;
int H,W,Map[105][105],dp[105][105],ans=1,a[105][105];
int main()
{
    scanf("%d%d",&H,&W);
    for(int i=1;i<=H;i++)
    {
        for(int j=1;j<=W;j++)
        {
            char c;
            cin>>c;
            if(c=='#')Map[i][j]=1;
        }
    }
    a[1][1]=1;
    dp[1][1]=1;
    for(int i=1;i<=H;i++)
    {
        for(int j=1;j<=W;j++)
        {
            if(Map[i][j]==0)
            {
                int t=0;
                if(a[i-1][j])t=max(t,dp[i-1][j]);
                if(a[i][j-1])t=max(t,dp[i][j-1]);
                if(t)
                {
                    a[i][j]=1;
                    dp[i][j]=t+1;
                    ans=max(ans,dp[i][j]);
                }
            }
        }
    }
    cout<<ans;
}

 

#808. 最长同余子数组

 附加文件 统计

给定一个 N长数组 {A}, 元素之间 两两不同.

现在要求你找出最长的 连续子序列, 使得这些元素 (modM) 意义下同余, 其中 M≥2.

形式化的说, 在数组中找到最长的 A[L..R],∃M≥2, 使得:

AL≡AL+1≡AL+2≡⋯≡AR(modM)

其中, a≡b(modM)即是说 a%M=b%M

输出此长度即可.

数据规模

  • 1≤n≤2×10^3
  • 1≤ai≤10^18

输入格式

第一行一个数字 N。

接下来一行 N 个整数 A1,A2,…,AN。

输出格式

一个数,表示最长连续同余子序列的长度。

样例输入

4
8 2 10 5

样例输出

3

注意到 8,2,10 均为偶数.


bonus1: consider what if N is greater (even 1≤N≤2×10^5)?

bonus2: consider how to solve the 'subsequence' version.

#include<bits/stdc++.h>
using namespace std;
long long a[2003],ans=1,N,b[2003];
long long gcd(long long a,long long b)
{
    return b==0?a:gcd(b,a%b);
}
int main()
{
   scanf("%lld",&N);
   for(int i=1;i<=N;i++)
   {
       scanf("%lld",&a[i]);
       b[i]=(a[i]-a[i-1]>=0?(a[i]-a[i-1]):(a[i-1]-a[i]));
   }
   for(long long i=2;i<N;i++)
   {
       long long ggg=b[i];
       for(long long j=i+1;j<=N;j++)
       {
            ggg=gcd(ggg,b[j]);
            if(ggg<2&&ggg!=0)break;
//           cout<<i<<" "<<j<<" "<<ggg<<endl;
           if(ggg>=2||ggg==0)ans=max(ans,j-i+2);
       }
   }
   cout<<ans<<endl;
}

 

#812. 互质

 附加文件 统计

题目描述

给你一个包含n个正整数的序列 A=(A1,A2,...,An),找到 [1,m]中每一个满足下列条件的 k:

gcd(Ai,k)=1, 1≤i≤n

输入描述

第一行输入两个整数 n, m 第二行输入n个整数代表序列A

输出描述

第一行输出一个整数代表满足条件的k的数量 接下里每一行输出一个整数,代表一个满足条件的k

样例输入

3 12
6 1 5

样例输出

3
1
7
11

数据范围

1≤n,m≤100000 1≤ai≤100000

#include<bits/stdc++.h>
using namespace std;
int a[100005],n,m,ans,ff[100005],mmm[100005];
vector<int>aa;
set<int>ss;
int gcd(int a,int b)
{
    return b==0?a:gcd(b,a%b);
}
void ffff(int x)
{
    if(mmm[x]==1)return;
    else mmm[x]=1;
    if(x==1)
    {
        return;
    }
    if(x%2==0)ss.insert(2);
    while(x%2==0)x/=2;
    int t=3;
    while(x!=1)
    {
        if(x%t==0)
        {
            ss.insert(t);
            x/=t;
        }
        else t+=2;
    }
}
int main()
{
   scanf("%d%d",&n,&m);
   for(int i=1;i<=n;i++)
   {
       scanf("%d",&a[i]);
       ffff(a[i]);
   }
   for(auto it=ss.begin();it!=ss.end();it++)
   {
       int tt=*it;
       while(tt<=m)
       {
           ff[tt]=1;
           tt+=*it;
       }
   }
   for(int i=1;i<=m;i++)
   {
       if(ff[i]==0)
       {
           aa.push_back(i);
           ans++;
       }
   }
   cout<<ans<<endl;
   for(int i=0;i<aa.size();i++)printf("%d\n",aa[i]);
}

最短路计数

 附加文件 统计

题目描述

给出一个 N 个顶点 M条边的无向无权图。

问从顶点 1 开始,到其他每个点的最短路有几条。

输入格式

第 1 行包含两个正整数 N,M。

接下来 M行,每行两个正整数 x,y 表示存在一条由顶点 x到顶点 y的边。(可能存在重边和自环)

输出格式

输出 N行,每行一个非负整数。

第 i行输出从顶点 1 到顶点 i 的不同最短路个数。

由于数据可能很大,你只需要输出 ansmod100003的结果。

若顶点 1不能到达顶点 i,请输出 0。

样例输入

5 7
1 2
1 3
2 4
3 4
2 3
4 5
4 5

样例输出

1
1
1
2
4

数据范围

1≤N≤10^6,1≤M≤2×10^6。

提示

由于数据量较大,请使用较为快速的输入/输出方式。

#include<bits/stdc++.h>
using namespace std;
int N,vis[20];
long long A[20][20],ans;
void dfs(int s=0,long long r=0)
{
    if(s==N)
    {
        ans=max(ans,r);
        return ;
    }
    for(int i=1;i<=2*N;i++)
    {
        if(vis[i])continue;
        vis[i]=1;
        for(int j=i+1;j<=2*N;j++)
        {
            if(vis[j])continue;
            vis[j]=1;
            int res=r ^ A[i][j];
            dfs(s+1,res);
            vis[j]=0;
        }
        vis[i]=0;
    }
}
int main()
{
    scanf("%d",&N);
    for(int i=1;i<2*N;i++)
    {
        for(int j=i+1;j<=2*N;j++)
        {
            scanf("%lld",&A[i][j]);
            A[j][i]=A[i][j];
        }
    }
    dfs();
    cout<<ans<<endl;
}

 

最后的舞会

 附加文件 统计

老师为即将毕业的同学们准备了一场舞会,有2N个同学会参加这场舞会,他们会被分成N对跳舞,每个人有一个编号,如果编号为i的同学和编号为j的同学配对,那么这一对的满意度是Ai,j(i<j),我们规定这个舞会的满意度为每一队的满意度的异或和,也就是说,当同学们分成N组后,第i对同学的满意度为Ai,那么舞会的满意度为A1⊕A2⊕...AN

请你求出本场舞会满意度的最大值

输入描述

第一行给出一个数N,有2N个人参加舞会

接下来给出一个矩阵表示i和j配对时的满意度

A1,2,A1,3,...A1,2N

A2,3,...A2,2N

.. .. ..

A2N−1,2N

其中1≤N≤8,0≤Ai,j≤2^30

输出描述

输出本场舞会满意度的最大值

样例输入

2
4 0 1
5 3
2

样例输出

6

样例解释

如果{1,2},{3,4},ans=A1,2⊕A3,4=4⊕2=6

如果{1,3},{2,4},ans=A1,3⊕A2,4=0⊕3=3

如果{1,4},{2,3},ans=A1,4⊕A2,3=1⊕5=4

最后答案为max(6,3,4)=6

#include<bits/stdc++.h>
using namespace std;
int N,vis[20];
long long A[20][20],ans;
void dfs(int s=0,long long r=0,int n=0)
{
    if(s==N)
    {
        ans=max(ans,r);
        return ;
    }
    for(int i=n+1;i<=2*N;i++)
    {
        if(vis[i])continue;
        vis[i]=1;
        for(int j=i+1;j<=2*N;j++)
        {
            if(vis[j])continue;
            vis[j]=1;
            int res=r ^ A[i][j];
            dfs(s+1,res,i);
            vis[j]=0;
        }
        vis[i]=0;
    }
}
int main()
{
    scanf("%d",&N);
    for(int i=1;i<2*N;i++)
    {
        for(int j=i+1;j<=2*N;j++)
        {
            scanf("%lld",&A[i][j]);
            A[j][i]=A[i][j];
        }
    }
    dfs();
    printf("%lld\n",ans);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值