*设有字符串 X,我们称在 X 的头尾及中间插入任意多个空格后构成的新字符串为 X 的扩展串,如字符串 X为“abcbcd”,则字符串“abcb□cd”,“□a□bcbcd□” 和 “abcb□cd□” 都是 X 的扩展串,这里“ □ ”代表空格字符。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e3+10;
char s1[maxn];
char s2[maxn];
int dp[maxn][maxn];//已经匹配好s1的前i位和s2的前j位
int k;
int main(){
scanf("%s%s%d",s1+1,s2+1,&k);
memset(dp,0x3f,sizeof(dp));
int len1 = strlen(s1+1);
int len2 = strlen(s2+1);
dp[0][0] = 0;
for(int i = 1;i <= len1;++i)dp[i][0] = k*i;
for(int i = 1;i <= len2;++i)dp[0][i] = k*i;
for(int i = 1;i <= len1;++i){
for(int j = 1;j <= len2;++j){
dp[i][j] = min(dp[i-1][j-1] + abs(s1[i] - s2[j]),min(dp[i][j-1] + k,dp[i-1][j] + k));
}
}
printf("%d\n",dp[len1][len2]);
return 0;
}
#include <cstdio>
#define ll long long
using namespace std;
const int N = 105, M = 1157621;//M是105*105*105中最大质数
const int N3 = N*N*N;
int n, a[N][N], b[N][N];
ll s[2][N][N];//存前缀和
struct Node {
int k, x, y, next;
}h[N3];//链表
int head[N3], tot;
int Ha(int k, int x, int y, int p) {//求Hash值
x--, y--;
return (int)(s[p][x+k][y+k] - s[p][x][y+k] - s[p][x+k][y] + s[p][x][y]) % M;//通过前缀和求期间和
}
void Add(int k, int i, int j) {//在Hash表中添加,挺像加边操作
int ha = Ha(k, i, j, 0);
h[++tot] = (Node) {k, i, j, head[ha]};
head[ha] = tot;
}
bool Judge(int n, int k, int x, int y) {//判断是否相同
if (h[n].k != k) return 0;
for (int i = 0; i < k; ++i)
for (int j = 0; j < k; ++j)
if (a[h[n].x+i][h[n].y+j] != b[x+i][y+j])
return 0;
return 1;
}
bool Find(int k, int x, int y) {
int ha = Ha(k, x, y, 1);
if (!head[ha]) return 0;
for (int i = head[ha]; i; i = h[i].next)//遍历这条链
if (Judge(i, k, x, y)) return 1;
return 0;
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j)
scanf("%d", &a[i][j]),
s[0][i][j] = s[0][i-1][j] + s[0][i][j-1] - s[0][i-1][j-1] + a[i][j];
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j)
scanf("%d", &b[i][j]),
s[1][i][j] = s[1][i-1][j] + s[1][i][j-1] - s[1][i-1][j-1] + b[i][j];
for (int k = 1; k <= n; ++k)
for (int i = 1; i + k - 1 <= n; ++i)
for (int j = 1; j + k - 1 <= n; ++j)
Add(k, i, j);//将第一个图的所有子矩阵加入
for (int k = n; k >= 1; --k)//从大到小枚举,找到了直接输出,这个for也可以二分
for (int i = 1; i + k - 1 <= n; ++i)
for (int j = 1; j + k - 1 <= n; ++j)
if (Find(k, i, j)) return printf("%d\n", k), 0;
puts("0");
return 0;
}
N
答案
1000
840
#include<cstdio>
#include<cstring>
#include<algorithm>
const int N=1e7+10;
const int pri[]={0,2,3,5,7,11,13,17,19,23,29};
int ans,Mx,n;
void dfs(int x,int d,int idx,int c){
if(d > Mx || (d == Mx && x < ans))Mx = d,ans = x;
for(int j = 1;j <= c;++j){
if(n < (long long)pri[idx] * x)return;
x *= pri[idx];
dfs(x,d * (j + 1),idx + 1,j);
}
}
int main(){
scanf("%d",&n);
dfs(1,1,1,31);
printf("%d\n",ans);
}
#include<bits/stdc++.h>
using namespace std;
const int maxn = 5e5+10;
int pos[maxn];
int next[maxn];
int ans;
int vis[maxn];
struct node{
int val,next;
node(){
next = 0x3f3f3f3f;
val = 0;
}
node(int X,int Y){
next = Y;
val = X;
}
bool operator <(const node &x)const{
return next < x.next;
}
}a[maxn];
priority_queue<node> q;
int main(){
//freopen("in","r",stdin);
int n,k,m;scanf("%d%d%d",&n,&k,&m);
for(int i = 1;i <= m;++i)scanf("%d",&a[i].val);
for(int i = m;i;--i){
if(pos[a[i].val])a[i].next = pos[a[i].val];
pos[a[i].val] = i;
}
for(int i = 1;i <= m;++i){
if(!vis[a[i].val]){
if(ans >= k){
int now = q.top().val;
vis[now] = 0;
q.pop();
}
ans++;
vis[a[i].val] = 1;
}
q.push(node(a[i].val,a[i].next));
}
printf("%d\n",ans);
return 0;
}
原文:https://www.cnblogs.com/2004-08-20/p/13405948.html