2024.11.13
今日总结
1:http://www.nfls.com.cn:20035/contest/2085/problem/1
这道题考察了字符串哈希,没学过,今天上午学习了字符串哈希
点击查看代码
#include <bits/stdc++.h>
using namespace std;
const long long p = 1e9 + 7;
string s;
unsigned long long int base[1000005], h1[1000005], h2[1000005], sum = 0;
int n;
bool check(int x, int d)
{
int l = x - d + 1, r = x + d;
if (h1[r] - h1[l - 1] * base[r - l + 1] == h2[l] - h2[r + 1] * base[r - l + 1])
{
return true;
}
return false;
}
int main()
{
cin >> n;
cin >> s;
s = ' ' + s;
for (int i = 1; i <= n; i++)
{
h1[i] = h1[i - 1] * p + (s[i] == '1');
}
for (int i = n; i >= 1; i--)
{
h2[i] = h2[i + 1] * p + (s[i] == '0');
}
base[0] = 1;
for (int i = 1; i <= n; i++)
{
base[i] = base[i - 1] * p;
}
for (int i = 1; i < n; i++)
{
int l = 0, r = min(i, n - i), mid, ans;
while (l <= r)
{
mid = (l + r) >> 1;
if (check(i, mid))
{
ans = mid, l = mid + 1;
}
else
{
r = mid - 1;
}
}
sum += ans;
}
cout << sum;
return 0;
}
2:http://www.nfls.com.cn:20035/contest/2090/problem/6
这道题是一道树形Dp的题目,主要复习了树形Dp的Dp建立含义,转移的方式
点击查看代码
//dp[i][j]是以i为根的子树操作j次后满足所需能剩下的最多金币。
#include<bits/stdc++.h>
using namespace std;
const int N = 2010;
const int INF = 0x3f3f3f3f;
int n,x;
int val[N],siz[N],dp[N][N],f[N];
vector<int> vec[N];
void dfs(int u,int fa)
{
dp[u][0] = x - val[u];//剩余金币数量
siz[u] = 1;
for(int i = 0;i < vec[u].size();i ++)
{
int v = vec[u][i];
if(v == fa) continue;
dfs(v,u);
siz[u] += siz[v];
memset(f,-0x3f,sizeof(f));
for(int j = siz[u] - 1;j >= 0;j --)
{
for(int k = siz[v] - 1;k >= 0;k --)
{
if(j - k - 1 >= 0) f[j] = max(f[j],dp[v][k] + dp[u][j - k - 1]);
if(dp[v][k] >= 0 && j - k >= 0) f[j] = max(f[j],dp[u][j - k]);
}
}
for(int j = siz[u];j >= 0;j --) dp[u][j] = f[j];
}
}
int main()
{
scanf("%d%d",&n,&x);
for(int i = 1;i <= n;i ++)
scanf("%d",&val[i]);
for(int i = 1;i < n;i ++)
{
int u,v;
scanf("%d%d",&u,&v);
vec[u].push_back(v);
vec[v].push_back(u);
}
memset(dp,-0x3f,sizeof(dp));
dfs(1,0);
int ans = INF;
for(int i = 0;i < n;i ++)
{
if(dp[1][i] >= 0)
{
printf("%d\n",i);
return 0;
}
}
return 0;
}
3:http://www.nfls.com.cn:20035/contest/2082/problem/1
这道题是一道简单的贪心,与排队接水的贪心思路一样
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N = 5e4 + 10;
int n,m,d,l,id,ans;
int sp[N],total[N];
int main()
{
scanf("%d%d%d%d",&n,&m,&d,&l);
for(int i = 1;i <= n;i ++)
scanf("%d",&sp[i]);
sort(sp + 1,sp + 1 + n);
int x = 1;
while(x <= n)
{
while(sp[x] - total[id] * d < l && x <= n) x ++;
if(x > n) break;
ans ++;
total[id] ++;
id ++;
x ++;
if(id == m) id = 0;
}
printf("%d\n",ans);
return 0;
}
4:http://www.nfls.com.cn:20035/contest/2090/problem/5#
这道题是一个状压Dp,复习了状压Dp状态的表示和转移方法,将其想象为可以和不可以
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N = 450;
int n,m,cnt;
int head[16],nxt[N],to[N],calc[1 << 16],dp[16][1 << 16][8];
void dfs(int id,int s,int h)
{
if(dp[id][s][h] != -1) return;
if((1 << h) < calc[s])
{
dp[id][s][h] = 0;
return;
}
if(s == (1 << id))
{
dp[id][s][h] = 1;
return;
}
if(h == 0)
{
dp[id][s][h] = 0;
return;
}
dp[id][s][h] = 0;
int i,j;
for(i = s & (s - 1);i;i = (i - 1) & s)
{
if((1 << id) & i) continue;
for(j = head[id];j != -1;j = nxt[j])
{
if(!((1 << to[j]) & s)) continue;
if(!((1 << to[j]) & i)) continue;
dfs(id,s - i,h - 1),dfs(to[j],i,h - 1);
dp[id][s][h] += dp[id][s - i][h - 1] * dp[to[j]][i][h - 1];
}
}
}
int main()
{
int i,j,id,num;
while(scanf("%d %d",&n,&m) != EOF)
{
memset(head,-1,sizeof(head));
memset(dp,-1,sizeof(dp));
memset(calc,0,sizeof(calc));
cnt = 0,id = 0,num = 1;
while(num < n)
{
num *= 2;
id ++;
}
m --;
for(i = 0;i < (1 << n);i ++)
for(j = 0;j < n;j ++)
if((1 << j) & i) calc[i] ++;
for(i = 0;i < n;i ++)
{
for(j = 0;j < n;j ++)
{
scanf("%d",&num);
if(num == 1)
{
nxt[cnt] = head[i];
to[cnt] = j;
head[i] = cnt;
cnt ++;
}
}
}
dfs(m,(1 << n) - 1,id);
printf("%d\n",dp[m][(1 << n) - 1][id]);
}
return 0;
}