8.3考试总结(NOIP模拟19)[最长不下降子序列·完全背包问题·最近公共祖先]
一定要保护自己的梦想,即使牺牲一切。
前言
把人给考没了。。。
看出来 T1 是一个周期性的东西了,先是打了一个暴力,想着打完 T2 T3 暴力就回来打。。
然后,就看着 T2 上头了,后来发现是看错题了,码完暴力就已经 2.5h 了
接下来就会开始看 T3 看到了部分分非常令人欣喜(码起主席树根本停不下来)。
一直到考试结束都没想起我那 T1 。
T1 最长不下降子序列
解题思路
对于比较小的数据可以直接 \(mathcal{O(nlogn)}\) 求出来(洗提 30 pts)
发现对于同一递推式,同一膜数,一定会有一个不大于膜数的周期(抽屉原理)
当出现一个与之前相同的数字时,后面的数其实也是一样的。
然后整个序列就成了三部分:最前面的散的+可以被划分成几个周期的区间+不完整的周期
接下来先对于第一部分以及它后面的一个周期可以直接暴力求出来。
并且以此类推直接将后面的区间中周期数加上就好了。
对于第三部分的转移不可以只向前倒一个周期,这样是不对的。
所有可以向前倒 周期个周期 这样就可以完美地解决这个问题了。
边界问题需要卡一下。
最后一个问题,如果运算的答案比正确答案少 1 怎么办??加上不就好了,有问题么,没有问题。(反正我的边界是这么卡出来的)
code(调试信息未删)
#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"Pass"<<endl
using namespace std;
inline int read()
{
int x=0,f=1;
char ch=getchar();
while(ch>'9'||ch<'0')
{
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
const int N=1e6+10,INF=1e18;
int n,a,b,c,d,T,t0,beg,len,ans,f[N],s[N],pos[N];
int cnt,lsh[N],tre[N];
int lowbit(int x)
{
return x&(-x);
}
int ask(int x)
{
int temp=0;
for(int i=x;i<=cnt+1;i+=lowbit(i))
temp=max(temp,tre[i]);//,cout<<i<<endl;
return temp;
}
void add(int x,int num)
{
for(int i=x;i;i-=lowbit(i))
tre[i]=max(tre[i],num);//,cout<<i<<endl;
}
void Special_Judge()
{
lsh[++cnt]=-INF;
lsh[++cnt]=s[1]=t0;
for(int i=2;i<=n;i++)
lsh[++cnt]=s[i]=(a*s[i-1]%d*s[i-1]%d+b*s[i-1]%d+c)%d;
sort(lsh+1,lsh+cnt+1);
cnt=unique(lsh+1,lsh+cnt+1)-lsh-1;
for(int i=1;i<=n;i++)
s[i]=lower_bound(lsh+1,lsh+cnt+1,s[i])-lsh;
// for(int i=1;i<=cnt;i++) cout<<lsh[i]<<' ';
for(int i=1;i<=n;i++)
{
f[i]=ask(cnt+1-s[i])+1;
// cout<<f[i]<<' ';
add(cnt+1-s[i],f[i]);
ans=max(ans,f[i]);
}
printf("%lld",ans);
// cout<<endl;for(int i=1;i<=n;i++) cout<<s[i]<<' ';
exit(0);
}
signed main()
{
n=read();
t0=read();
a=read();
b=read();
c=read();
d=read();
s[1]=t0;
for(int i=2;i<=min(n,2*d);i++)
{
s[i]=(a*s[i-1]%d*s[i-1]%d+b*s[i-1]%d+c)%d;//,cout<<s[i]<<' ';
// cout<<s[i]<<endl;
}
// f();
for(int i=1;i<=min(n,2*d);i++)
{
// cout<<i<<' '<<s[i]<<endl;
if(pos[s[i]])
{
// cout<<s[i]<<' '<<pos[s[i]]<<endl;
T=i-pos[s[i]];
beg=pos[s[i]];
break;
}
else pos[s[i]]=i;
}
if(!beg||T*T+beg-1>=n||n<=1e6) Special_Judge();
// f();
// cout<<T<<' '<<beg<<endl;
cnt=1000;
for(int i=1;i<=beg+T-1;i++)
{
// f();
// cout<<s[i]<<' '<<cnt<<endl;
f[i]=ask(cnt-s[i]+1)+1;
// if(f[i]) f();
add(cnt-s[i]+1,f[i]);
}
// f();
// cout<<(n-beg+1)/T<<endl;
for(int i=1;i<=T;i++)
{
// f();
f[i]=f[i+beg-1]+(n-beg+1)/T-T;
ans=max(f[i],ans);
// cout<<f[i]<<endl;
}
// for(int i=1;i<=10;i++) cout<<s[i]<<' ';
// for(int i=beg;i<=beg+T-1;i++) cout<<s[i]<<' ';cout<<endl;
len=(n-beg+1)%T;
s[0]=s[beg+T-1];
for(int i=1;i<=T*T+len-1;i++)
s[i]=(a*s[i-1]%d*s[i-1]%d+b*s[i-1]%d+c)%d;
// for(int i=1;i<=T+len-1;i++) cout<<s[i]<<' ';
memset(tre,0,sizeof(tre));
/*
for(int i=1;i<=T;i++)
{
// cout<<f[i]<<' ';
f[i]=max(f[i],ask(cnt-s[i]+1)+1);
// cout<<ask(cnt-s[i]+1)+1<<endl;
// cout<<f[i]<<endl;
add(cnt-s[i]+1,f[i]);
}
// */
// cout<<T<<' '<<beg<<' '<<len<<endl;
for(int i=1;i<=T;i++)
{
memset(tre,0,sizeof(tre));
for(int j=i;j<=T;j++)
add(cnt-s[j]+1,f[j]);
for(int j=T+1;j<=((len>0)?T*T+len-1:T*T);j++)
{
// cout<<s[j]<<' ';
int temp=ask(cnt-s[j]+1)+1;
// cout<<temp<<endl;
ans=max(ans,temp);
add(cnt-s[j]+1,temp);
}
}
printf("%lld",ans);
return 0;
}
T2 完全背包问题
解题思路
有一个新知识:同余最短路。
通俗来讲就是其它的数对于整个序列中最小的数字(这样时间复杂度较小)取膜后。
所得到的余数,对于更大的数只要与序列最小数取膜后余数也是这个,那么就一定可以通过序列中某些数字的组合得到。
然后发现这个题的 DP 可以对于前几个物品,选择了几个有限制的物品,以及对于序列最小数取膜之后的值进行维护。
有限制的物品比较好考虑,主要是没有限制的。
如果枚举的话,可以枚举到正无穷,显然这样是不可以的。
因此考虑上面提到的同余最短路,若干个相同数字的加和取膜最终一定会得到之前取膜得到过的数。
对于这个性质,我们可以直接跑最短路,但是也可以对于没一个“环”进行维护。
每加入一个数,就更新相同数的不同余数的最小值,可以递归实现。
然后应用到此题上就是对于每一个加入的没有限制的数,直接通过两个循环分别找到这个“环”并且进行更新就好了。
对于所有的都有限制的数据进行特殊处理就好了(题库好像并没有这样的数据)
code
#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"Pass"<<endl
using namespace std;
inline int read()
{
int x=0,f=1;
char ch=getchar();
while(ch>'9'||ch<'0')
{
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
const int N=1e4+10,M=3e5+10,INF=4557430888798830399ll;
int n,m,l,c,s[60],f[60][N];
bool vis[60][N];
bitset<M> bj[60];
void solve1()
{
bj[0][0]=true;
for(int i=1;i<=n;i++)
for(int j=1;j<=c;j++)
bj[j]|=bj[j-1]<<s[i];
for(int i=1,x;i<=m;i++)
{
bool jud=false;
x=read();
for(int j=0;j<=c;j++)
if(bj[j][x])
{
jud=true;
break;
}
if(jud) printf("Yes\n");
else printf("No\n");
}
}
void solve2()
{
memset(f,0x3f,sizeof(f));
f[0][0]=0;
for(int i=2;i<=n;i++)
if(s[i]<l)
{
memset(vis,false,sizeof(vis));
for(int j=0;j<=c;j++)
for(int k=0;k<s[1];k++)
if(!vis[j][k])
{
int temp=k,minn=INF,id,now;
while(!vis[j][temp])
{
vis[j][temp]=true;
if(minn>f[j][temp])
{
minn=f[j][temp];
id=temp;
}
temp=(temp+s[i])%s[1];
}
now=(id+s[i])%s[1];
while(now!=id)
{
f[j][now]=min(f[j][now],minn+s[i]);
minn=f[j][now];
now=(now+s[i])%s[1];
}
}
}
else
for(int j=1;j<=c;j++)
for(int k=0;k<s[1];k++)
f[j][k]=min(f[j][k],f[j-1][((k-s[i])%s[1]+s[1])%s[1]]+s[i]);
for(int i=1,x;i<=m;i++)
{
x=read();
bool jud=false;
for(int j=0;j<=c;j++)
if(f[j][x%s[1]]<=x&&f[j][x%s[1]]!=INF)
{
jud=true;
break;
}
if(jud) printf("Yes\n");
else printf("No\n");
}
}
signed main()
{
n=read();
m=read();
for(int i=1;i<=n;i++)
s[i]=read();
l=read();
c=read();
sort(s+1,s+n+1);
if(s[1]>=l) solve1();
else solve2();
return 0;
}
T3 最近公共祖先
解题思路
可以说是本次考试中最水的题了。
不难发现对于每一个新加入的黑点,造成影响的其实只有以下几部分:
以该黑色节点为根节点的子树。
该黑色节点的所有祖先以及各级祖先除了该节点所在子树的子树。
然后直接在 DFS 序上维护线段树,区间修改单点查询,然后在已经更改过的节点打上标记就好了。
考场是看上了那个部分分,然后码了棵主席树,然后我就炸了。。
code
正解
#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"Pass"<<endl
#define ls x<<1
#define rs x<<1|1
using namespace std;
inline int read()
{
int x=0,f=1;
char ch=getchar();
while(ch>'9'||ch<'0')
{
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
const int N=2e5+10;
int n,m,s[N],top,sta[N];
int tim,id[N],fa[N],siz[N],dfn[N],dep[N];
int all,root[N];
int tot=1,head[N],nxt[N],ver[N];
int vis[N],flag;
string ch;
void add(int x,int y)
{
ver[++tot]=y;
nxt[tot]=head[x];
head[x]=tot;
}
struct Segment_Tree
{
int dat,laz;
}tre[N<<2];
void dfs(int x)
{
siz[x]=1;
dfn[x]=++tim;
id[tim]=x;
for(int i=head[x];i;i=nxt[i])
{
int to=ver[i];
if(to==fa[x]) continue;
fa[to]=x;
dep[to]=dep[x]+1;
dfs(to);
siz[x]+=siz[to];
}
}
void push_down(int x)
{
if(!tre[x].laz) return ;
tre[ls].laz=max(tre[ls].laz,tre[x].laz);
tre[rs].laz=max(tre[rs].laz,tre[x].laz);
tre[ls].dat=max(tre[ls].dat,tre[x].laz);
tre[rs].dat=max(tre[rs].dat,tre[x].laz);
tre[x].laz=0;
}
void push_up(int x)
{
tre[x].dat=max(tre[ls].dat,tre[rs].dat);
}
void update(int x,int l,int r,int L,int R,int num)
{
if(L>R) return ;
if(L<=l&&r<=R)
{
tre[x].dat=max(tre[x].dat,num);
tre[x].laz=max(tre[x].laz,num);
return ;
}
push_down(x);
int mid=(l+r)>>1;
if(L<=mid) update(ls,l,mid,L,R,num);
if(R>mid) update(rs,mid+1,r,L,R,num);
push_up(x);
}
int query(int x,int l,int r,int pos)
{
if(l==r) return tre[x].dat;
push_down(x);
int mid=(l+r)>>1;
if(pos<=mid) return query(ls,l,mid,pos);
return query(rs,mid+1,r,pos);
}
void change(int x)
{
update(1,1,tim,dfn[x],dfn[x]+siz[x]-1,s[x]);
while(x&&!vis[x])
{
vis[x]++;
update(1,1,tim,dfn[fa[x]],dfn[x]-1,s[fa[x]]);
update(1,1,tim,dfn[x]+siz[x],dfn[fa[x]]+siz[fa[x]]-1,s[fa[x]]);
x=fa[x];
}
}
signed main()
{
vis[1]=true;
n=read();
m=read();
for(int i=1;i<=n;i++)
s[i]=read();
for(int i=1,x,y;i<n;i++)
{
x=read();
y=read();
add(x,y);
add(y,x);
}
dfs(1);
for(int i=1,opt,x;i<=m;i++)
{
cin>>ch>>x;
if(ch[0]=='M')
{
flag=true;
change(x);
}
else if(!flag) printf("%d\n",-1);
else printf("%lld\n",query(1,1,tim,dfn[x]));
}
return 0;
}
35pts 主席树
#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"Pass"<<endl
#define ls tre[x].l
#define rs tre[x].r
using namespace std;
inline int read()
{
int x=0,f=1;
char ch=getchar();
while(ch>'9'||ch<'0')
{
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
const int N=2e5+10;
int n,m,s[N],top,sta[N];
int tim,fa[N],siz[N],dfn[N],dep[N],topp[N],son[N];
int all,root[N];
int cnt,lsh[N];
int tot=1,head[N],nxt[N],ver[N];
bool flag=false;
int vis[N];
void add(int x,int y)
{
ver[++tot]=y;
nxt[tot]=head[x];
head[x]=tot;
}
struct Node
{
int opt,x;
}q[N];
struct Segment_Tree
{
int l,r,siz;
}tre[N*80];
int insert(int pre,int l,int r,int pos)
{
int x=++all;
tre[x]=tre[pre];
tre[x].siz++;
if(l==r) return x;
int mid=(l+r)>>1;
if(pos<=mid) ls=insert(tre[pre].l,l,mid,pos);
else rs=insert(tre[pre].r,mid+1,r,pos);
return x;
}
void dfs(int x)
{
if(vis[x]>=2)
{
for(int i=head[x];i;i=nxt[i])
if(fa[ver[i]]==x)
{
root[ver[i]]=insert(root[x],1,cnt,s[x]);
dfs(ver[i]);
}
}
else if(vis[x]==1)
{
// f();
// cout<<"Check: "<<x<<endl;
for(int i=head[x];i;i=nxt[i])
if(fa[ver[i]]==x)
{
if(!vis[ver[i]]) root[ver[i]]=insert(root[x],1,cnt,s[x]);
else root[ver[i]]=root[x];
dfs(ver[i]);
}
}
else
{
for(int i=head[x];i;i=nxt[i])
if(fa[ver[i]]==x)
{
root[ver[i]]=root[x];
dfs(ver[i]);
}
}
}
void dfs3(int x)
{
// f();
// cout<<x<<endl;
if(vis[x]) vis[x]=2;
for(int i=head[x];i;i=nxt[i])
{
int to=ver[i];
if(to==fa[x]) continue;
dfs3(to);
vis[x]+=(vis[to]!=0);
}
// cout<<"Check: "<<x<<' '<<vis[x]<<endl;
}
int query(int pre,int x,int l,int r)
{
if(l==r) return l;
int mid=(l+r)>>1,rsum=tre[rs].siz-tre[tre[pre].r].siz;
if(rsum) return query(tre[pre].r,rs,mid+1,r);
return query(tre[pre].l,ls,l,mid);
}
bool b[N];
void Special_Judge()
{
add(0,1);
int tmp=0;
for(int i=1;i<=m;i++)
if(!q[i].opt)
vis[q[i].x]=b[q[i].x]=1,tmp++;
sort(lsh+1,lsh+cnt+1);
cnt=unique(lsh+1,lsh+cnt+1)-lsh-1;
for(int i=1;i<=n;i++)
s[i]=lower_bound(lsh+1,lsh+cnt+1,s[i])-lsh;
dfs3(1);
dfs(0);
for(int i=1,ans;i<=m;i++)
{
if(!q[i].opt) continue;
if(b[q[i].x]) ans=lsh[s[q[i].x]];
else ans=0;
for(int j=head[q[i].x];j;j=nxt[j])
if(vis[ver[j]])
{
ans=max(ans,lsh[s[q[i].x]]);
break;
}
if(!tmp) printf("%lld\n",-1ll);
else printf("%lld\n",max(ans,lsh[query(root[0],root[q[i].x],1,cnt)]));
}
exit(0);
}
void dfs1(int x)
{
siz[x]=1;
for(int i=head[x];i;i=nxt[i])
{
int to=ver[i];
if(siz[to]) continue;
fa[to]=x;
dep[to]=dep[x]+1;
dfs1(to);
siz[x]+=siz[to];
if(siz[to]>siz[son[x]])
son[x]=to;
}
}
void dfs2(int x,int tp)
{
dfn[x]=++tim;
topp[x]=tp;
if(son[x]) dfs2(son[x],tp);
for(int i=head[x];i;i=nxt[i])
if(!dfn[ver[i]])
dfs2(ver[i],ver[i]);
}
int LCA(int x,int y)
{
if(!x||!y) return 0;
while(topp[x]^topp[y])
{
if(dep[topp[x]]<dep[topp[y]])
swap(x,y);
x=fa[topp[x]];
}
if(dep[x]>dep[y])
swap(x,y);
return x;
}
signed main()
{
n=read();
m=read();
for(int i=1;i<=n;i++)
lsh[++cnt]=s[i]=read();
for(int i=1,x,y;i<n;i++)
{
x=read();
y=read();
add(x,y);
add(y,x);
}
for(int i=1;i<=m;i++)
{
string ch;
cin>>ch;
q[i].x=read();
if(ch[0]=='Q') q[i].opt=1;
else q[i].opt=0;
if(!q[i].opt&&q[i-1].opt)
flag=true;
}
dfs1(1);
dfs2(1,1);
if(!flag) Special_Judge();
for(int i=1;i<=m;i++)
if(!q[i].opt) sta[++top]=q[i].x;
else if(!top) printf("%lld\n",-1ll);
else
{
int maxn=0;
for(int j=1;j<=top;j++)
maxn=max(maxn,s[LCA(sta[j],q[i].x)]);
printf("%lld\n",maxn);
}
return 0;
}
8.3考试总结(NOIP模拟19)[最长不下降子序列·完全背包问题·最近公共祖先]的更多相关文章
- [考试总结]noip模拟19
连挂3场 \(\color{green}{\huge{\text{菜}}}\) 真 . 挂分王 ... 没什么好说的了,菜就是了. \(T1\) 一波手推想到了性质 \(1\),然后因为数组原因挂成比 ...
- 6.17考试总结(NOIP模拟8)[星际旅行·砍树·超级树·求和]
6.17考试总结(NOIP模拟8) 背景 考得不咋样,有一个非常遗憾的地方:最后一题少取膜了,\(100pts->40pts\),改了这么多年的错还是头一回看见以下的情景... T1星际旅行 前 ...
- 5.23考试总结(NOIP模拟2)
5.23考试总结(NOIP模拟2) 洛谷题单 看第一题第一眼,不好打呀;看第一题样例又一眼,诶,我直接一手小阶乘走人 然后就急忙去干T2T3了 后来考完一看,只有\(T1\)骗到了\(15pts\)[ ...
- 5.22考试总结(NOIP模拟1)
5.22考试总结(NOIP模拟1) 改题记录 T1 序列 题解 暴力思路很好想,分数也很好想\(QAQ\) (反正我只拿了5pts) 正解的话: 先用欧拉筛把1-n的素数筛出来 void get_Pr ...
- 2021.8.3考试总结[NOIP模拟29]
T1 最长不下降子序列 数据范围$1e18$很不妙,但模数$d$只有$150$,考虑从这里突破. 计算的式子是个二次函数,结果只与上一个值有关,而模$d$情况下值最多只有$150$个,就证明序列会出现 ...
- 2021.9.17考试总结[NOIP模拟55]
有的考试表面上自称NOIP模拟,背地里却是绍兴一中NOI模拟 吓得我直接文件打错 T1 Skip 设状态$f_i$为最后一次选$i$在$i$时的最优解.有$f_i=max_{j<i}[f_j+a ...
- [考试总结]noip模拟23
因为考试过多,所以学校的博客就暂时咕掉了,放到家里来写 不过话说,vscode的markdown编辑器还是真的很好用 先把 \(noip\) 模拟 \(23\) 的总结写了吧.. 俗话说:" ...
- [考试总结]noip模拟41
发现长时间鸽博客会导致 rp--,所以今天来补一补 这个题目其实不是很毒瘤,然而是非常毒瘤... 题目不说请就是非常非常的烦人 首先 \(T1\) 就整整有两个歧义的地方,也就是说我们一共有 \(4\ ...
- [考试反思]NOIP模拟测试19:洗礼
[]260 []230[]210 []200[8]170[9]160 这套题一般,数据很弱,T1T2暴力都能A,而且都是一些思维题,想不到就爆0. 原因不明,很多一直很强的人在这一次滑铁卢了,于是我个 ...
随机推荐
- 关于MySql数据库误操作数据找回的办法
先讲个事,前段时间,系统长时间不用的一个功能被开放出来了,想当然的我没有在测试平台上测试,直接操作了正式系统(的确是我不严谨),导致好多数据异常,页面展示错乱了.于是我想到的第一个就是进行备份还原.项 ...
- [UWP] WinUI 2.6 使用指南
2021年6月24日,Windows 11 正式对外发布,对于UWP开发者来说,这一天同样值得纪念,因为WinUI 2.6也正式发布了! 相同的时间点意味着一件事,即WinUI 2.6和Windows ...
- sql数据库新建作业,新建步骤时报错从 IClassFactory 为 CLSID 为 {AA40D1D6-CAEF-4A56-B9BB-D0D3DC976BA2} 的 COM 组件创建实例失败,原因是出现以下错误: c001f011。 (Microsoft.SqlServer.ManagedDTS)
简单粗暴的重启sql数据库 其他网上找的方法 32位操作系统: 打开运行(命令提示符), 一.输入 cd c:\windows\system32 进入到c:\windows\system32路径中 二 ...
- 痞子衡嵌入式:在串口波特率识别实例里逐步展示i.MXRT上提升代码执行性能的十八般武艺
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是在串口波特率识别实例里逐步展示i.MXRT上提升代码执行性能的十八般武艺. 恩智浦 MCU SE 团队近期一直在加班加点赶 SBL 项目 ...
- 【Azure 应用程序见解】Application Insights Java Agent 3.1.0的使用实验,通过修改单个URL的采样率来减少请求及依赖项的数据采集
问题描述 近日好消息,如果是一个Java Spring Cloud的项目,想使用Azure Applicaiton Insights来收集日志及一些应用程序见解.但是有不愿意集成SDK来修改代码或者配 ...
- SpringBoot:springBoot注解大全
springboot源码下载 https://github.com/spring-projects/spring-boot/releases 一.注解(annotations)列表 @SpringBo ...
- 在CentOS7上面部署项目,报出找不到表的错误
最近在linux服务器上面部署一个javaweb的项目,报出一些奇怪的错误,拉到报错信息的最下面显示mysql数据库的某个表找不到,可以在windows上面是能正常运行的. 最后发现原来是linux服 ...
- SpringCloud的Ribbon自定义负载均衡算法
1.Ribbon默认使用RoundRobinRule策略轮询选择server 策略名 策略声明 策略描述 实现说明 BestAvailableRule public class BestAvailab ...
- python logger 动态设置日志名
代码: import logging logger = logging.getLogger('') logger.setLevel(level=logging.INFO) def setLogName ...
- Shell常用工具find,grep,sed,awk,xargs命令
最近学习shell命令,对grep,sed,awk命令有点混乱,故小结一下,巩固一遍. 注意:find , grep , sed, awk可使用基本正则表达式字符,find,grep,awk也支持扩展 ...