1001调查问卷
题解
由于每个问卷的问题只有两个选项,并且 m≤10 m ≤ 10 那么所有问题的状态为 210=1024 2 1 0 = 1024 种答案, n≤103 n ≤ 10 3 ,那么直接枚举保留问题的状态暴力计算就行
#include <bits/stdc++.h>
using namespace std;
char s[11];
int data[1100][11];
int n,T,m,k;
int num[1100];
int sum[1100];
int Get(int col,int bit)
{
int numb = 0;
int result = 0;
while(bit)
{
if(bit %2)
{
result = result *2 + data[col][numb];
}
numb++;
bit /=2;
}
return result;
}
int main()
{
scanf("%d",&T);
for(int Case = 1; Case <= T; Case ++)
{
scanf("%d %d %d",&n,&m,&k);
for(int i = 0; i<n; i++)
{
scanf("%s",s);
for(int j = 0; j<m; j++)
{
data[i][j] = s[j] == 'A'?1:0;
}
}
int OutResult = 0;
for(int i = 1; i<=((1<<m)-1); i++)
{
memset(num,0,sizeof(num));
for(int j = 0; j<n; j++)
{
num[Get(j,i)]++;
}
sum[1024] = 0;
for(int j = 1023; j >= 0; j--)
{
sum[j] = sum[j+1] + num[j];
}
int result = 0;
for(int j = 0; j<1024; j++)
{
result = result+num[j]*sum[j+1];
}
if(result >=k)
OutResult++;
}
printf("Case #%d: %d\n",Case,OutResult);
}
return 0;
}
1002 字串查询
题解
求解的是 [l,r] [ l , r ] 中最小非空子串的个数,那么最小非空子串肯定是在 [l,r] [ l , r ] 上长度为1的最小字母(思考?),那么我们只需要维持一个 n×26 n × 26 的前缀和数组 dp[i][j] d p [ i ] [ j ] 表示以i结尾的第j个字母的前缀和。每次查询都是遍历这个区间的26个字母,找最小的字母的个数就行
#include <bits/stdc++.h>
using namespace std;
const int Max = 110000;
int num[Max][26];
char str[Max];
int main()
{
int T;
int n,q;
int l,r;
scanf("%d",&T);
for(int Case =1; Case<=T;Case++)
{
scanf("%d %d",&n,&q);
scanf("%s",str);
int len = strlen(str);
for(int i = 0;i<26;i++) num[0][i] = 0;
for(int i = 0;i<len;i++)
{
for(int j = 0;j<26;j++) num[i+1][j] = num[i][j];
num[i+1][str[i]-'A'] ++;
}
printf("Case #%d:\n",Case);
while(q--)
{
scanf("%d %d",&l,&r);
int result = 0;
for(int i = 0;i<26;i++)
{
result = num[r][i]-num[l-1][i];
if(result)
break;
}
printf("%d\n",result);
}
}
return 0;
}
1006 三原色图
题解
选出k个边使得权值和最小,并且满足边的限制条件。对于一个无向图,最小需要 n−1 n − 1 条边才能使每一个连通,那么对于限制条件,我们可以分别去求一个最小生成树,将在生成树中的边进行标记,然后从小到大进行遍历虽有的边,经不在树中的边加入,然后将两种限制条件的结果取最小就是所要求的结果。
#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
struct node
{
int u,v;
int value,num;
int flag;
} edge[1100];
int n,m;
int pre[110];
int resultR[1100],resultB[1100];
bool cmp(node a,node b)
{
return a.value < b.value;
}
int Find(int x)
{
return pre[x] == 0?x:pre[x] = Find(pre[x]);
}
void Union(int x,int y)
{
int Fx = Find(x);
int Fy = Find(y);
if(Fx != Fy)
{
pre[Fx] = Fy;
}
}
bool visR[1100],visB[1100];
int Kuras(int limit,bool * vis)
{
int ans = 0;
int num = 0;
memset(pre,0,sizeof(pre));
for(int i = 0; i<m; i++)
{
if(edge[i].flag != limit && Find(edge[i].u) != Find(edge[i].v))
{
vis[edge[i].num] = true;
ans += edge[i].value;
Union(edge[i].u,edge[i].v);
num++;
}
if(num == n-1)
{
return ans;
}
}
ans = INF;
return ans;
}
int main()
{
int T;
char s[2];
scanf("%d",&T);
for(int Case = 1; Case <= T; Case ++)
{
scanf("%d %d",&n,&m);
for(int i = 0; i<m; i++)
{
scanf("%d %d %d %s",&edge[i].u,&edge[i].v,&edge[i].value,s);
if(s[0] == 'R')
edge[i].flag = 1;
else if(s[0] == 'G')
edge[i].flag = 2;
else if(s[0] == 'B')
edge[i].flag = 3;
}
sort(edge,edge+m,cmp);
for(int i = 0; i<m; i++)
{
edge[i].num = i;
}
memset(visB,false,sizeof(visB));
memset(visR,false,sizeof(visR));
int ansR = Kuras(3,visR);
int ansB = Kuras(1,visB);
memset(resultR,INF,sizeof(resultR));
memset(resultB,INF,sizeof(resultB));
int k = n-1;
resultR[k] = ansR;
resultB[k] = ansB;
for(int i = 0; i<m; i++)
{
if(!visR[i])
{
resultR[k+1] = min(resultR[k+1],resultR[k]+edge[i].value);
k++;
}
}
k = n-1;
for(int i = 0; i<m; i++)
{
if(!visB[i])
{
resultB[k+1] = min(resultB[k+1],resultB[k]+edge[i].value);
k++;
}
}
printf("Case #%d:\n",Case);
for(int i = 1; i<=m; i++)
{
int re = min(resultR[i],resultB[i]);
if(re >= INF)
printf("-1\n");
else
printf("%d\n",re);
}
}
return 0;
}
其余的题大家可以参考官方题解,博主会在空闲时间将题补了
补题
1005 序列计数 HDU6348
从小到大计算子序列的长度,可以根据长度小的推长度大的序列的个数,使用树状数组来优化,由于期望的最长上升子序列并不大,可以暴力一下o( ̄▽ ̄)o
#include <stdio.h>
#include <stdlib.h>
#include <cstring>
#include <iostream>
using namespace std;
const int Max = 1e4+100;
const int Mod = 1e9+7;
int num[Max];
int tree[Max*4];
int arr[Max];
int n;
int lowbit(int x)
{
return x&(-x);
}
void add(int x,int v)
{
while(x<n)
{
tree[x] = (tree[x] +v)%Mod;
x += lowbit(x);
}
}
int Query(int x)
{
long long ans = 0;
while(x)
{
ans = (ans + tree[x])%Mod;
x-=lowbit(x);
}
return ans;
}
int main()
{
int T;
scanf("%d",&T);
for(int Case = 1; Case <= T; Case ++)
{
scanf("%d",&n);
for(int i = 0;i<n;i++)
{
scanf("%d",&arr[i]);
num[i] = 1;
}
int len = n;
long long result = n;
printf("Case #%d:",Case);
while(result)
{
printf(" %lld",(result%Mod));
result =0;
len --;
memset(tree,0,sizeof(tree));
for(int i = 0;i<n;i++)
{
add(arr[i],num[i]);
num[i] = Query(arr[i]-1);
result = (result + num[i])%Mod;
}
}
while(len--) printf(" 0");
printf("\n");
}
return 0;
}