A: 最大下降矩阵 - LIS
时间限制: 1 Sec 内存限制: 512 MB
提交: 720 解决: 193
[提交] [状态] [讨论版] [命题人:外部导入]
题目描述
我们称一个矩阵是下降矩阵,当且仅当,矩阵的每一列都是严格下降的。很显然,这个要求很苛刻,大多数矩阵都无法满足。但是显然如果消去一些行,一定可以使得这个矩阵变成下降矩阵。
现在给出一个n行m列的矩阵,请你求出最少消去多少行,可以使得这个矩阵变为下降矩阵。
输入
输入第一行包含两个正整数n,m分别表示矩阵的行数和列数。(1<=n,m<=300)
接下来n行,每行有m个数,中间用空格隔开,每个数都小于2^31.
输出
输出仅包含一个整数,即最少消去的行数。
样例输入 Copy
1 3
1 2 3
样例输出 Copy
0
提示
样例二
输入
3 1
3
1
2
输出
1
思路:
把矩阵的每一行看成是一个数,对列求最长下降子序
代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<stack>
#include<cmath>
#include<set>
#include<map>
using namespace std;
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef pair<int,int>P;
const int INF=0x3f3f3f3f;
const int N=315;
int a[N][N],dp[N];
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%d",&a[i][j]);
}
}
int mx=-INF;
for(int i=1;i<=n;i++){
dp[i]=1;
for(int j=i-1;j>=1;j--){
int flag=0;
for(int k=1;k<=m;k++){
if(a[j][k]<=a[i][k])flag=1;
}
//printf("flag=%d\n",flag);
if(!flag){
//printf("%d %d\n",dp[j]+1,dp[i]);
dp[i]=max(dp[j]+1,dp[i]);
}
}
mx=max(dp[i],mx);
}
printf("%d\n",n-mx);
}
D: 文本修正 - 模拟
时间限制: 1 Sec 内存限制: 256 MB
提交: 698 解决: 295
[提交] [状态] [讨论版] [命题人:外部导入]
题目描述
Chika接到了去检查河南省算法竞赛题面的任务,她发现所有单词"Henan"的首字母都没有大写。她需要去修正文本中的所有错误。换句话说,她需要把所有单词"henan"的首字母从"h"替换为"H",同时保留文本的其余部分不变。你能帮助她吗?
输入
输入文件仅包含一行,包含被空格分割开的单词,代表Chika被要求去检查的文本。输入的字符总数不超过200,只含有大小写字母和空格。要注意,只有被空格分割开的仅包含字母的连续串才被称为“单词”。
输出
输出文件应该只包含一行,代表你修正后的文本。
样例输入 Copy
Hello henan algorithm contest
样例输出 Copy
Hello Henan algorithm contest
思路:
模拟一下就好了,注意是“被空格分割的”字符
代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<stack>
#include<cmath>
#include<set>
#include<map>
using namespace std;
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef pair<int,int>P;
const int INF=0x3f3f3f3f;
const int N=115;
int main(){
string s;
getline(cin,s);
int len=s.length();
if(len>5&&s[0]=='h'&&s[1]=='e'&&s[2]=='n'&&s[3]=='a'&&s[4]=='n'&&s[5]==' '){
s[0]='H';
}
else if(len==5&&s[0]=='h'&&s[1]=='e'&&s[2]=='n'&&s[3]=='a'&&s[4]=='n'){
s[0]='H';
}
if(len>5&&s[len-6]==' '&&s[len-5]=='h'&&s[len-4]=='e'&&s[len-3]=='n'&&s[len-2]=='a'&&s[len-1]=='n'){
s[len-5]='H';
}
for(int i=1;i<len;i++){
if(i+5<len&&s[i-1]==' '&&s[i]=='h'&&s[i+1]=='e'&&s[i+2]=='n'&&s[i+3]=='a'&&s[i+4]=='n'&&s[i+5]==' '){
s[i]='H';
}
}
cout<<s<<endl;
}
E: 咕咕的的复复读读机机 - 模拟
时间限制: 1 Sec 内存限制: 64 MB
提交: 508 解决: 290
[提交] [状态] [讨论版] [命题人:外部导入]
题目描述
咕咕一直想买台复读机,今天他终于走进了一家卖复读机的小店!这里有很多很多的复读机,咕咕看中 了一台相貌平平无奇的,他决定试用一下这台复读机的功能。然而,当他打开复读机的开关后,复读机 说了 n 个数字,而且这些数字不完全一样——作为一台复读机,怎么会这样呢?看到满脸疑惑的咕咕, 店员说道:” 这是一台带有自动加噪的复读机,它虽然 n 次中说的数字不完全一样,但是它所复读的 那个数字永远会在这 n 次中出现次数最多!”
于是,聪明的你,知道这 n 个数字之后,你能猜出那个数字是它所复读的数字吗?
于是,聪明的你,知道这 n 个数字之后,你能猜出那个数字是它所复读的数字吗?
输入
第一行一个数字 n(1 ≤ n ≤ 100)。
第二行有 n 个数字(范围在 [1,100] 之间),表示这台复读机所说的 n 个数字。
这台复读机保证它所复读的那个数字是唯一的!
输出
输出那个数字。
样例输入 Copy
3
2 4 2
样例输出 Copy
2
提示
样例二
输入
5
1 1 100 99 87
输出
1
思路:
就判断谁出现最多就好了
代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<stack>
#include<cmath>
#include<set>
#include<map>
using namespace std;
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef pair<int,int>P;
const int INF=0x3f3f3f3f;
const int N=115;
int a[N],cnt[N];
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
cnt[a[i]]++;
}
int mx=0,ans;
for(int i=1;i<=n;i++){
if(mx<cnt[a[i]]){
ans=a[i];
mx=cnt[a[i]];
}
}
printf("%d\n",ans);
}
F: 咕咕的计数题 II
时间限制: 1 Sec 内存限制: 64 MB
提交: 1432 解决: 143
[提交] [状态] [讨论版] [命题人:外部导入]
题目描述
咕咕最近在学习初等数论,并且对下取整函数产生了极大的兴趣。下取整函数是指一个函数,自变量为 一个实数,因变量为一个整数,这个整数恰好是小于或等于自变量的最大的整数,通常记做 ⌊x⌋。例如, ⌊2.5⌋ = 2,⌊2⌋ = 2,⌊−2.5⌋ = −3。
咕咕发现,给定一个 a,并不是所有的自然数 n 都存在一个正整数 i 使得 ⌊n/i⌋ = a。那么,如果给定 l,r,咕咕好奇在区间 [l,r] 中有多少个正整数能使这个等式有正整数解 i 呢?
那么,聪明的你,你能告诉咕咕吗?
输入
第一行有一个整数 T(1 ≤ T ≤ 106),表示数据组数。接下来有 T 行,每行有三个数 a,l,r(1 ≤ a ≤ 1018,1 ≤ l ≤ r ≤ 1018),表示一组询问。
输出
输出 T 行,对每组询问,输出一个整数表示答案。
样例输入 Copy
4
5 7 10
7 39 42
1000 1000 1000
27 100 1000
样例输出 Copy
1
2
1
617
思路:
可以看出来规律:对于数x,以下满足:
x*1
x*2 x*2+1
x*3 x*3+1 x*3+2
x*4 x*4+1 x*4+2 x*4+3
……
x*x以及以后
写的时候注意特判情况:
3 6 6
代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<stack>
#include<cmath>
#include<set>
#include<map>
using namespace std;
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef pair<int,int>P;
const int INF=0x3f3f3f3f;
const int N=115;
int main(){
int t;
ll a,l,r;
scanf("%d",&t);
while(t--){
scanf("%lld%lld%lld",&a,&l,&r);
ll ans=0,e=0,s,t;
int flag=0;
if(a<=(int)sqrt(l)+10){
if(a*a<=l){
printf("%lld\n",r-l+1);
continue;
}
}
if(a<=(int)sqrt(r)+10){
if(a*a<=r){
ans+=r-a*a+1;
e=a-1;
flag=1;
}
}
s=l/a;
if(!flag){
if(s*a<=l&&s*a+s-1>=r){
printf("%lld\n",r-l+1);
continue;
}
e=r/a;
t=a*e+e-1;
if(r<=t){
ans+=r-e*a+1;
e-=1;
}
}
t=s*a+s-1;
if(l<=t){
ans+=s;
ans-=(l-s*a);
}
s+=1;
if(s<=e)ans+=(s+e)*(e-s+1)/2;
printf("%lld\n",ans);
}
}
H: 咕咕的搜索序列 - LCA
时间限制: 1 Sec 内存限制: 128 MB
提交: 364 解决: 39
[提交] [状态] [讨论版] [命题人:外部导入]
题目描述
咕咕已经学到树上的深度优先搜索 (dfs) 啦!由于同一棵树不同的 dfs 访问结点的次序不一样,咕咕干脆定义 了一个搜索序列:一开始序列为空,而每次离开这个点,并且不会再返回这个点时,就把这个点加入序列中, 最后返回到根节点后也把根节点加入这个序列中,这样就定义了一个与 dfs 一一对应的搜索序列!而且这个 搜索序列,也是所有点的一个排列。
对于一棵有根树(结点标号 1 到 n,以 1 为根),咕咕对它跑了一遍 dfs 得到了搜索序列后,它准备把这个序 列抄在纸上拿给咸鱼看。但是,粗心的咕咕在抄这个序列的时候,一些点被它忽略了,纸上的序列只有 m 个 点。待咸鱼看到纸上这个序列后,咸鱼就很好奇:咕咕那么粗心,只是抄少了点这么简单吗,会不会同时把 一些点的位置也给变化了呢?
现在,聪明的你,你能判断出来咕咕在抄的时候有没有把点的位置变化了吗?也就是说,咕咕给的 m 个点的 序列,真的能够由一个 dfs 得到的搜索序列删除几个点后得到吗?
输入
第一行一个整数 T(1≤ T ≤106),表示有 T 组数据。
对于每组数据:
第一行有两个正整数 n 和 m(1≤m≤n≤106),表示树的点数和咕咕给的序列的点数。
第二行有 n−1 个正整数 a1,a2,··· ,an−1(1≤ ai ≤i),表示点 ai 是点 (i+1) 的父结点。
第三行有 m 个互不相同的正整数,b1,b2,··· ,bm(1≤bi ≤n),表示咕咕给的序列。
输入保证同一个测试点下的所有数据的 n 的和不超过 106。
输出
对每一组数据,输出一行。如果一定不能得到,输出 BAD GUGU ;否则输出 NOT BAD 。
样例输入 Copy
2
4 4
1 1 2
3 4 2 1
4 2
1 1
2 2 4
样例输出 Copy
NOT BAD
BAD GUGU
提示
对于样例中给定的树,只存在两个不同的所搜序列:(3,4,2,1) 和 (4,2,3,1)。故对于序列 (2,4) 是没有办法 由任意一个搜索序列只通过删除点得到的。
思路:
搜到一个点时,从这个点向下搜,这些点肯定在这个点之前都搜了,标记一下已访问。
然后每两个相邻的点i,i+1,找LCA,设LCA是点A
找到点i到点A的路上,最接近点A的点B,即点A的到i的下一层,若从i到i+1 ,dfs则,B以下的点肯定都搜过了标记一下
(dfs的过程是i先到B,再往i+1点的方向走,最后搜点A)
此时,若i+1已经访问过了,则输出“BAD GUGU”
代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<stack>
#include<cmath>
#include<set>
#include<map>
using namespace std;
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef pair<int,int>P;
const int INF=0x3f3f3f3f;
const int N=1000015;
int cnt,head[N];
struct A{
int to,nex;
}edge[N];
int q[N],vis[N],pre[N],dep[N];
void add(int from,int to){
edge[cnt].to=to;
edge[cnt].nex=head[from];
head[from]=cnt++;
}
void dfs(int now){
if(vis[now])return ;
vis[now]=1;
for(int i=head[now];i!=-1;i=edge[i].nex){
int v=edge[i].to;
dfs(v);
}
}
void dfs_dep(int now,int last){
dep[now]=dep[last]+1;
for(int i=head[now];i!=-1;i=edge[i].nex){
int v=edge[i].to;
dfs_dep(v,now);
}
}
int lca(int u,int v){
int lastu=u;
while(dep[u]>dep[v]){
lastu=u;
u=pre[u];
}
while(dep[v]>dep[u]){
v=pre[v];
}
if(u==v)return lastu;
while(pre[u]!=pre[v]){
u=pre[u];
v=pre[v];
}
return u;
}
int main(){
int t,n,m,a;
scanf("%d",&t);
while(t--){
int flag=0;
cnt=0;
scanf("%d%d",&n,&m);
//memset(edge,0,sizeof(edge));
for(int i=0;i<=n;i++)head[i]=-1;
for(int i=2;i<=n;i++){
scanf("%d",&a);
pre[i]=a;
add(a,i);
vis[i]=0;
}
vis[1]=0;
dfs_dep(1,0);
for(int i=1;i<=m;i++){
scanf("%d",&q[i]);
}
for(int i=1;i<m;i++){
dfs(q[i]);//把当前点的子树都标记为1
dfs(lca(q[i],q[i+1]));//找到B点
if(vis[q[i+1]]){
flag=1;
break;
}
}
if(flag)printf("BAD GUGU\n");
else printf("NOT BAD\n");
}
}
I: Childhood dream - 暴力+剪枝
时间限制: 1 Sec 内存限制: 256 MB
提交: 300 解决: 95
[提交] [状态] [讨论版] [命题人:外部导入]
题目描述
你童年时期就有一个梦想,想要加入 ACM(Association of Calculation and Magic),今天,这个机会终于 来了。
但是 ACM 只想要哪些天赋异禀的人, 比如像 tourist,他们给了你一道题来检测你是否足够机智。
猜一个长度为 m 数字串,总共有 n 个提示串,解释如下:
8640 0A2B
A 前面的数字说明与答案相比,有多少个位置上的数字是相同的。 B 前面的数字说明与答案相比,有多 少个数字是相同的,但是位置不一样。
0 A 就表示给出的串没有任何位置和答案是相同的。 2 B 就表示给出的串中有两个数字和答案相同,但 是位置不一样。
所以,对于上面那个提示串 6457 是一个合理的答案,但是 1234 并不是。
现在给你 N(N<=100) 个提示串(如上所示),你需要去找到一个数字串来符合每一个提示串的要求。
提示串中的每个数字都是不同的,即一个串中不会存在相同的数字。
你能解决这个问题并加入 ACM 吗?
输入
第一行两个数字,n(n<=100) 和 m(m<=9), 提示串的数量以及目标字符串的长度。
然后是 n 行,每行的格式如下:
s x y
s 是提示串,x 是 A 前的数字,y 是 B 前的数字,等同于:
s xAyB
输出
一行,目标串。
数据保证答案唯一。
样例输入 Copy
6 4
5164 3 0
5174 3 0
5194 3 0
5124 3 0
5134 3 0
5104 3 0
样例输出 Copy
5184
思路:
暴力即可,妹想到啊
代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<stack>
#include<cmath>
#include<set>
#include<map>
using namespace std;
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef pair<int,int>P;
const int INF=0x3f3f3f3f;
const int N=115;
int flag,n,m,a[N][N],p[N],x[N],y[N];
int judge(int m1){
for(int i=1;i<=n;i++){
int cnt1=0,cnt2=0;
for(int j=1;j<=m1;j++){
if(p[j]==a[i][j])cnt1++;
}
if(m1<m&&cnt1>x[i])return 0;
if(m1==m&&cnt1!=x[i])return 0;
for(int j=1;j<=m1;j++){
for(int k=1;k<=m1;k++){
if(j==k)continue;
if(a[i][j]==p[k]){
cnt2++;
break;
}
}
}
if(m1<m&&cnt2>y[i])return 0;
if(m1==m&&cnt2!=y[i])return 0;
}
return 1;
}
void dfs(int dep){
if(flag)return ;
if(dep==m+1){
flag=1;
for(int i=1;i<=m;i++){
printf("%d",p[i]);
}
printf("\n");
}
if(dep>m+1)return ;
for(int j=0;j<=9;j++){
p[dep]=j;
if(judge(dep))dfs(dep+1);
else continue;
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%1d",&a[i][j]);
}
scanf("%d%d",&x[i],&y[i]);
}
dfs(1);
}