#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);
}