A Monument For Heroes
题意:
给出n个字符串列表(长度不超过10),每个字符串只可以拼接在它前面的字串后面,且要求前面尾字母的字串与它的首字母相同,当拼接成一个字符串t后,要求t的首字母和尾字母相同,求可以拼接成的字符串t的最长长度。(1<=n<=2*10^5)
思路:
一直在想以每个字符串的首字母和尾字母作点连边,求一个有重边自环的最长路径环...其实就是一个线性DP啦,题解的做法很好,f[i][l][r]表示前i个字符串组成的左边字符是l,右边字符是r的最大长度。状态转移就是:当第i个串(l...r)时,f[i][j][r]=max(f[i-1][j][l]+w)。又是一类环形DP的做法
#include<bits/stdc++.h>
using namespace std;
const int N=200010;
struct ac{
int l,r,w;
} node[N];;
char str[20];
int f[30][30];
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%s",str);
int w=strlen(str);
node[i].w=w;
node[i].l=str[0]-'a';
node[i].r=str[w-1]-'a';
}
memset(f,-0x3f,sizeof f);
for(int i=0;i<26;++i) f[i][i]=0;
for(int i=1;i<=n;++i){
for(int j=0;j<26;++j){
int l=node[i].l,r=node[i].r,w=node[i].w;
f[j][r]=max(f[j][r],f[j][l]+w);
}
}
int res=0;
for(int i=0;i<26;++i) res=max(res,f[i][i]);
cout<<res<<endl;
return 0;
}
B Best Match
题意:
给出一个序列,求有多少种互为相反数(0和自己互为相反数)的二元组合
思路:
用map记录一个数出现的次数,set将所有出现的数记录,循环set统计
#include<bits/stdc++.h>
using namespace std;
set<int> S;
map<int,int> mmp;
int main(){
int n;
cin>>n;
for(int i=1;i<=n;++i){
int x;
cin>>x;
mmp[x]++;
S.insert(x);
}
long long res=0;
for(auto x: S){
if(x==0) res+=(1ll*mmp[0]*(mmp[0]-1)/2>0?1ll*mmp[0]*(mmp[0]-1)/2:0);
else
res+=1ll*mmp[x]*mmp[-x];
//cout<<x<<":"<<mmp[x]<<" "<<mmp[-x]<<endl;
mmp[x]=mmp[-x]=0;
}
cout<<res<<endl;
return 0;
}
D DIY Masks at Home
题意:
给出一个字母矩阵,找到只有一种字母的面积最大的正方形矩阵。矩阵(1≤n,m≤2000)
思路:
两种做法
DP
f[i,j]表示(i,j)作为正方形右下角的最大边长,只有当(i,j)和(i-1,j),(i,j-1),(i-1,j-1)相等时这个点才可以和左上方合并成一个更大的正方形,否则f[i,j]=1.(不容易想到用DP来做呀=_=)
#include<bits/stdc++.h>
using namespace std;
const int N=2010;
char g[N][N];
int f[N][N],n,m;
int main(){
int T;
cin>>T;
while(T--){
cin>>n>>m;
int ans=0;
memset(f,0,sizeof f);
for(int i=1;i<=n;++i) cin>>(g[i]+1);
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
if(g[i][j]==g[i-1][j]&&g[i][j]==g[i][j-1]&&g[i][j]==g[i-1][j-1]){
f[i][j]=min(f[i][j-1],min(f[i-1][j],f[i-1][j-1]))+1;
}
else f[i][j]=1;
ans=max(ans,f[i][j]);
}
}
cout<<ans<<endl;
}
return 0;
}
二分
首先预处理每个格子与自己相同且连续的最远的距离。二分枚举正方形边长l,先从列开始遍历,每一列从上到下记录连续最远距离大于l的长度是否大于l。
#include<bits/stdc++.h>
using namespace std;
const int N=2010;
char g[N][N];
int x[N][N],y[N][N],n,m;
bool check(int k){
for(int j=1;j<=m;++j){
int l=0;
for(int i=1;i<=n;++i){
if(x[i][j]-j+1>=k&&g[i-1][j]==g[i][j]) l++;
else if(x[i][j]-j+1>=k) l=1;
else l=0;
if(l>=k) {
return true;
}
}
}
return false;
}
int main(){
int T;
cin>>T;
while(T--){
cin>>n>>m;
for(int i=1;i<=n;++i) cin>>(g[i]+1);
for(int i=1;i<=n;++i){
int l=1;
for(int j=1;j<=m;++j)
if(g[i][j]!=g[i][l]){
for(int k=j-1;k>=l;--k)
x[i][k]=j-1;
l=j;
}
for(int j=l;j<=m;++j) x[i][j]=m;
}
int l=1,r=2010,ans=1;
while(l<=r){
int mid=(l+r)/2;
if(check(mid)){
ans=max(ans,mid);
l=mid+1;
}
else r=mid-1;
}
cout<<ans<<endl;
}
return 0;
}
E Yu is a Brutal Creature
题意:
1~n种有多数i满足((i*i+1)%i=0)
思路:
可以发现只有(1*1+1=2%1=0),所以...
代码
#include<bits/stdc++.h>
using namespace std;
int main(){
int cnt=0;
for(int i=0;i<=10000;++i){
if((1ll*i*i+1) %(i+1)==0){
++cnt;
//cout<<i<<" "<<1ll*i*i+1<<" "<<cnt<<endl;
}
}
int T;
cin>>T;
while(T--){
long long n;
cin>>n;
if(n==0) cout<<0<<endl;
else cout<<n-1<<endl;
}
return 0;
}