1.鸣人的影分身
ACWing1050. 鸣人的影分身
输入样例:
1
7 3
输出样例:
8
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 11;
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
int n, m;
cin >> m >>n;
int f[N][N] = {0};
f[0][0] = 1;//边界 总和是0, 选0个数的方案数是1
for(int i = 0; i <= m; i++)
for(int j = 1;j <= n; j++)
{
f[i][j] = f[i][j-1];
if(i >= j) f[i][j] += f[i-j][j];
}
printf("%d\n", f[m][n]);
}
return 0;
}
2.糖果
ACWing1047. 糖果
输入样例:
5 7
1
2
3
4
5
输出样例:
14
样例解释
Dzx的选择是2+3+4+5=14,这样糖果总数是7的倍数,并且是总数最多的选择。
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 110;
int f[N][N];//从i个数中选总数模k为j的方案中的最大值
int n, k;
int main()
{
cin >>n >>k;
memset(f,-0x3f,sizeof f);//f[0][1]、f[0][2]···无意义
f[0][0] = 0;//本题求的是最大值而不是方案数,因此为0
for(int i = 1; i <= n; i++)
{
int w;
scanf("%d", &w);
for(int j = 0; j <k; j++)
f[i][j] = max(f[i-1][j], f[i-1][(j+k-w%k)%k]+w);
}
printf("%d\n", f[n][0]);
return 0;
}
3.密码脱落
1222. 密码脱落
输入样例1:
ABCBA
输出样例1:
0
输入样例2:
ABDCDCBABC
输出样例2:
3
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 1010;
char s[N];
int f[N][N];
int main()
{
scanf("%s",s);
int n = strlen(s);
for(int len = 1; len <= n;len++)
for(int l = 0; l + len -1 <n; l++)
{
int r = l +len - 1;
if(len == 1) f[l][r] = 1;
else
{
if(s[l] == s[r]) f[l][r] = f[l+1][r-1]+2;
if(f[l][r-1] > f[l][r]) f[l][r] = f[l][r-1];
if(f[l+1][r] > f[l][r]) f[l][r] = f[l+1][r];
}
}
cout << n- f[0][n-1];
return 0;
}
4.生命之树
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long LL;
const int N = 100010, M = N*2;
int n, w[N], h[N],e[M],ne[M],idx;
LL f[N];
void add(int a,int b)
{
e[idx] = b;
ne[idx] = h[a];
h[a] = idx++;
}
void dfs(int u, int father)//标注父节点,防止往回搜
{
f[u] = w[u];
for(int i = h[u]; i != -1; i = ne[i])
{
int j = e[i];
if(j != father)
{
dfs(j,u);
f[u] += max(0ll,f[j]);
}
}
}
int main()
{
cin >>n;
memset(h,-1,sizeof h);
for(int i = 1; i <= n; i++) scanf("%d", &w[i]);
for(int i = 0; i <n-1; i++)
{
int a, b;
cin >> a >> b;
add(a,b),add(b,a);//无向边
}
dfs(1,-1);
LL res = f[1];
for(int i = 2; i <= n; i++) res = max(res, f[i]);
cout << res <<endl;
return 0;
}
5. 斐波那契前 n 项和
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long LL;
const int N =3;
int n,m;
void mul(int c[],int a[],int b[][N])
{
int temp[N] = {0};
for(int i = 0; i <N; i++)
for(int j = 0; j <N; j++)
temp[i] = (temp[i] +(LL)a[j]*b[j][i])%m;
memcpy(c,temp,sizeof temp);
}
void mul(int c[][N],int a[][N], int b[][N])
{
int temp[N][N]={0};
for(int i = 0; i <N; i++)
for(int j = 0; j < N; j++)
for(int k = 0; k < N; k++)
temp[i][j] = (temp[i][j] +(LL)a[i][k]*b[k][j])%m;
memcpy(c,temp,sizeof temp);
}
int main()
{
cin >> n >>m;
int f1[N]={1,1,1};
int a[N][N] = {{0,1,0},{1,1,1},{0,0,1}};
n--;
while(n)
{
if(n & 1) mul(f1,f1,a);
mul(a,a,a);//a = a*a
n >>= 1;
}
cout << f1[2] <<endl;
return 0;
}
6. 包子凑数
AcWing1226. 包子凑数
输入格式
第一行包含一个整数 N。
接下来 N 行,每行包含一个整数 Ai。
输出格式
输出一个整数代表答案。
如果凑不出的数目有无限多个,输出INF。
数据范围
1≤N≤100,
1≤Ai≤100
输入样例1:
2
4
5
输出样例1:
6
输入样例2:
2
4
6
输出样例2:
INF
样例解释
对于样例1,凑不出的数目包括:1, 2, 3, 6, 7, 11。
对于样例2,所有奇数都凑不出来,所以有无限多个。
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 10010;
int a[110];
bool f[110][N];
int gcd(int a,int b)
{
return b?gcd(b,a%b):a;
}
int main()
{
int n;
cin >>n;
int d = 0;
for(int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
d = gcd(d,a[i]);
}
if(d != 1) puts("INF");
else
{
f[0][0] = true;
for(int i = 1; i <= n; i++)
for(int j = 0;j <N; j++)
{
f[i][j] = f[i-1][j];
if(j >= a[i]) f[i][j] |= f[i][j-a[i]];
}
int res = 0;
for(int i = 0;i <N; i++)
if(!f[n][i]) res++;
cout << res;
}
return 0;
}
一维做法
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 10010;
int a[110];
bool f[N];
int gcd(int a, int b)
{
return b ? gcd(b, a % b) : a;
}
int main()
{
int n;
scanf("%d", &n);
int d = 0;
for (int i = 1; i <= n; i ++ )
{
scanf("%d", &a[i]);
d = gcd(d, a[i]);
}
if (d != 1) puts("INF");
else
{
f[0] = true;
for (int i = 1; i <= n; i ++ )
for (int j = a[i]; j < N; j ++ )
f[j] |= f[j - a[i]];
int res = 0;
for (int i = 0; i < N; i ++ )
if (!f[i])
res ++ ;
printf("%d\n", res);
}
return 0;
}
7. 括号配对
Acwing1070. 括号配对
输入样例:
[])
输出样例:
1
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 110, inf = 0x3f3f3f3f;
char s[N];
int f[N][N]; // f[i][j]代表将i~j个字符变成GBE的所有方案的集合的最小值
bool check(int a, int b)
{
if (s[a] == '[' && s[b] == ']' || s[a] == '(' && s[b] ==')') return true;
return false;
}
int main()
{
scanf("%s", s + 1);
int n = strlen(s + 1);
for (int len = 1; len <= n; len++)
for (int l = 1; l + len - 1 <= n; l++)//循环左右端点
{
int r = l + len - 1;
if (len == 1) f[l][r] = 1;
else
{
f[l][r] = inf;
if (check(l, r)) f[l][r] = min(f[l][r], f[l + 1][r - 1]);//左右匹配
for (int k = l; k <= r; k++)
f[l][r] = min(f[l][r], f[l][k] + f[k + 1][r]);
}
}
cout << f[1][n] << endl;
return 0;
}
8. 旅游规划
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 200010, M = N*2;
int n, h[N],e[M],ne[M],idx,d1[N],d2[N],p1[N],up[N];
int maxd;
void add(int a,int b)
{
e[idx] = b;
ne[idx] = h[a];
h[a] = idx++;
}
void dfs_d(int u, int father)
{
for(int i = h[u]; i != -1;i = ne[i])
{
int j =e[i];
if(j != father)
{
dfs_d(j,u);
int dist = d1[j]+1;
if(dist > d1[u])
{
d2[u] = d1[u],d1[u] = dist;
p1[u] = j;
}
else if(dist > d2[u]) d2[u] = dist;
}
}
maxd = max(maxd,d1[u]+d2[u]);
}
void dfs_u(int u,int father)
{
for(int i = h[u]; i != -1; i = ne[i])
{
int j = e[i];
if(j != father)
{
up[j] = up[u]+1;
if(p1[u] == j) up[j] = max(up[j],d2[u]+1);
else up[j] = max(up[j], d1[u]+1);
dfs_u(j,u);
}
}
}
int main()
{
cin >>n;
memset(h,-1,sizeof h);
for(int i = 0;i <n - 1; i++)
{
int a, b;
cin >> a >> b;
add(a,b),add(b,a);
}
dfs_d(0,-1);
dfs_u(0,-1);//搜索往上走的最大值
for(int i = 0; i <n; i++)
{
int d[3] = {d1[i],d2[i],up[i]};
sort(d,d+3);
if(d[1]+d[2] == maxd) cout << i << endl;
}
return 0;
}