CSP-S模拟13排序 Xorum 有趣的区间问题 无聊的卡牌问题

T1【构造+规律】:给你一个排列,要你求逆序对数量,把原序列的逆序对位置当成交换,进行任意排列使得最后序列升序。(n<=1000)

一:排列的实质是id[i]=i的一一对应,问题互相转化会更简单。原序列i-->a[i]转化成a[i]-->i,b[a[i]]=i
发现强制原序列逆序对已经通过下标保证,满足交换次数=逆序对数的操作方法就是冒泡排序一遍。
二:如果需要把每个逆序对用上,说明每次操作只能消除一个逆序对,所以每次交换相邻的值的位置,不改变其他的逆序对。

点击查看代码






#include<bits/stdc++.h>
using namespace std;
#define _f(i,a,b) for(register int i=a;i<=b;++i)
#define f_(i,a,b) for(register int i=a;i>=b;--i)
#define chu printf
#define ll long long
#define rint register int
#define ull unsigned long long
inline ll re()
{
    ll x=0,h=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')h=-1;
        ch=getchar();
    }
    while(ch<='9'&&ch>='0')
    {
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*h;
}
const int N=1100;
int n,a[N],b[N];
int cnt;
int main()
{
  // freopen("1.in","r",stdin);
  // freopen("1.out","w",stdout);
  n=re();
  _f(i,1,n)a[i]=re(),b[a[i]]=i;
  _f(i,1,n)
  _f(j,i+1,n)
  if(a[j]<a[i])cnt++;
  chu("%d\n",cnt);
  _f(i,1,n)//每次把b里面i换到i位置
  {
      int pos=0;
      _f(j,i+1,n)
      if(b[j]==i)
      {pos=j;break;}
      f_(j,pos,i+1)
      {
          swap(b[j],b[j-1]);
          chu("%d %d\n",min(b[j],b[j-1]),max(b[j],b[j-1]));
      }
  }
    return 0;
}
/*
5
5 1 3 4 2

10
7 3 4 2 5 6 10 9 8 1
*/

T2【构造/随机化】给你一个数x(x<=1e6),是奇数,要求你每次选出已有的2个数,(1)c=a^b(2)c=a+b

产生新的数,最后产生1,操作次数不超过1e5。

一:就是让产生的数相差1而且必须是奇数>偶数<,考虑如果gcd(a,b)=1,ax-by=1有解,所以先随机产生(a,b),然后exgcd求解,最后验证是否合法。提高正解率:先算加,再算异或,减少重复。

点击查看代码








#include<bits/stdc++.h>
using namespace std;
#define _f(i,a,b) for(register int i=a;i<=b;++i)
#define f_(i,a,b) for(register int i=a;i>=b;--i)
#define chu printf
#define ll long long
#define rint register int
#define ull unsigned long long
inline ll re()
{
    ll x=0,h=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')h=-1;
        ch=getchar();
    }
    while(ch<='9'&&ch>='0')
    {
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*h;
}
const int N=510;
ll g[100000+100];int cnt,tot;
struct Operation
{
    ll op,x,y;
}e[100000+100];
map<ll,bool>mp;
inline void print(int len)
{
    chu("%d\n",len);
    _f(i,1,len)
    {
       chu("%lld %lld %lld\n",e[i].op,e[i].x,e[i].y);
    }
    exit(0);
}
ll xx,yy;
inline ll exgcd(ll ar,ll br)
{
    if(br==0)
    {
        xx=1,yy=0;return ar;
    }
    ll Gcd=exgcd(br,ar%br);
    ll tmp=xx;
    xx=yy;
    yy=tmp-ar/br*yy;
    return Gcd;
}
inline ll gcd(ll ar,ll br)
{
    if(!br)return ar;
    return gcd(br,ar%br);
}
inline void Deal_end(ll a1,ll a2)//就是2个数互质解方程
{
   // chu("has find:%lld  %lld\n",a1,a2);
    exgcd(a1,a2);//求解线性
    //x+=b/a*gcd
    while(xx<0)xx+=a2,yy-=a1;
    while(yy>0)yy-=a1,xx+=a2;
    yy=-yy;
  //  chu("is a solution:%lld %lld\n",xx,yy);
   // chu("up to now time is:%d\n",tot);
  //  _f(i,1,tot)
  //  chu("%d %d %d\n",e[i].op,e[i].x,e[i].y);
  //  chu("fuck you wrong!\n");
 //   _f(i,1,xx-1)e[++tot]=(Operation){1,a1*i,a1};
    if(((a1*xx)^(a2*yy))!=1)return ;
    int lgx=log2(xx),lgy=log2(yy);
    if(lgx+(xx-((1<<((int)log2(xx)))))+lgy+(yy-((1<<((int)log2(yy)))))+tot>100000)return;
    //if(xx+yy+tot>100000)return;
    for(rint i=1;i*2<=xx;i<<=1)
    {
        e[++tot]=(Operation){1,a1*i,a1*i};
    }
    int has=1<<((int)log2(xx));
    int lef=xx-has;
    _f(i,1,lef)e[++tot]=(Operation){1,a1*(has+i-1),a1};
    for(rint i=1;i*2<=yy;i<<=1)
    {
        e[++tot]=(Operation){1,a2*i,a2*i};
    }
    has=1<<((int)log2(yy));
    lef=yy-has;
   // _f(i,1,yy-1)e[++tot]=(Operation){1,a2*i,a2};
    _f(i,1,lef)e[++tot]=(Operation){1,a2*(has+i-1),a2};
    e[++tot]=(Operation){2,a1*xx,a2*yy};
   // chu("tot has:%d\n",tot);
    print(tot);
    return ;
}
int main()
{
  // freopen("1.in","r",stdin);
  // freopen("1.out","w",stdout);
   g[++cnt]=re();
   mp[g[cnt]]=1;
   if(g[cnt]==1)
   {
       chu("%d",0);
       return 0;
   }
   g[cnt+1]=g[cnt]+g[cnt];++cnt;
   e[++tot]=(Operation){1,g[cnt-1],g[cnt-1]};
   mp[g[cnt]]=1;
   int add=1;
   if(gcd(g[cnt],g[cnt-1])==1)
   {
       Deal_end(cnt,cnt-1);
   }
   while(cnt<=100000+10)//开始找
   {
       int ad=add;add=0;int nowcnt=cnt;
      // chu("new_round:%d\n",tot);
   //   chu("the new round")
       _f(ir,1,ad)//把last的数和新的
       {
           int i=nowcnt-ir+1;
           _f(j,1,nowcnt-ad)
           {
               if(gcd(g[i],g[j])==1)
               {
                   Deal_end(g[i],g[j]);
               }
                ll mayin=g[j]+g[i];
                if(mp.find(mayin)==mp.end())
                {
                    g[++cnt]=mayin;
                    e[++tot]=(Operation){1,g[i],g[j]};
                    mp[mayin]=1;
                    ++add;
                } 
                mayin=g[j]^g[i];
                if(mp.find(mayin)==mp.end())
                {
                    g[++cnt]=mayin;
                    e[++tot]=(Operation){2,g[i],g[j]};
                    mp[mayin]=1;
                    ++add;
                }
           }
       }
   }
    return 0;
}
/*
拿出2个数,异或放进去,和放进去,先查询是否已经满足要求,如果满足,就停止;
如果不满足,把新的数异或一遍,加一遍放进去,记录操作数

208899
*/

二:构造一组解。构造方法就是"1101"-->"1101000"-->+ and -->-->only 1-->to delete 1 from 1101000-->to delete 1from 1101-->a new smaller question\(O(logn^2)\)

点击查看代码






#include<bits/stdc++.h>
using namespace std;
#define _f(i,a,b) for(register int i=a;i<=b;++i)
#define f_(i,a,b) for(register int i=a;i>=b;--i)
#define chu printf
#define ll long long
#define rint register int
#define ull unsigned long long
inline ll re()
{
    ll x=0,h=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')h=-1;
        ch=getchar();
    }
    while(ch<='9'&&ch>='0')
    {
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*h;
}
const int N=510;
struct Op
{
    ll op,x,y;
}e[100000+100];
int cnt;
int main()
{
  // freopen("1.in","r",stdin);
  // freopen("1.out","w",stdout);
  ll a=re();
  if((a>>1)&1)//如果不是0
  {
      e[++cnt]=(Op){1,a,a};
      e[++cnt]=(Op){2,a*2,a};
      a=(a*2)^a;
  }

//     //得到了一个最高位是hig+1,剩下全部是0的数
    int _1=0;
    ll tmp=a;
    while(tmp)
    {
        tmp-=((tmp)&(-tmp));
        _1++;
    }
    _1--;
   // chu("many:%d  a:%lld\n",_1,a);
    _f(k,1,_1)//需要重复进行这么多次的操作把前面的1消掉
    {
        int hig=-1;
        ll tmp=a;
      //  chu("tmp:%lld\n",tmp);
        while(tmp){tmp>>=1;hig++;}//最高位1是第几位
      //  chu("out?:a:%lld\n",a);
     //   chu("hig:%d\n",hig);
        _f(i,1,hig)
        {
            e[++cnt]=(Op){1,a<<(i-1),a<<(i-1)};
        }
        ll b=a<<hig;//就是上面造出来的
     //   chu("b:%lld\n",b);
        //chu("b:%lld\n",b);
        e[++cnt]=(Op){1,a,b};
        e[++cnt]=(Op){2,a,b};
        e[++cnt]=(Op){2,(a+b),(a^b)};//if(cnt==16)chu("wrong:%d+%d  ^ %d^%d:%d\n",a,b,a,b,(a+b)^(a^b));
        ll wonder=(a+b)^(a^b);
       // chu("wondrt:%lld\n",wonder);
        int now_hig=hig+hig;
        ll ap=b;
        _f(j,hig+2,now_hig)
        {
            e[++cnt]=(Op){1,wonder,wonder};
          //  chu("cnt;%d\n",cnt);
            wonder=wonder*2;
           // chu("wonder:%lld\n",wonder);
            if((1ll<<j)&ap)
            {
               // chu("opp:%lld\n",1ll<<j);
                e[++cnt]=(Op){2,ap,wonder};ll opp=1ll<<j;
              //  chu("from:%lld-->%lld\n",ap,(ap^opp));
                ap=ap^opp;
            }
        }
       //ap
      //  chu("ap:%lld\n",ap);
        e[++cnt]=(Op){2,ap,a};
        a=(a^ap);
       // chu("a:%lld\n",a);
    }
    chu("%d\n",cnt);
    _f(i,1,cnt)
    {
        chu("%lld %lld %lld\n",e[i].op,e[i].x,e[i].y);
    }
    return 0;
}
/*
*/

T3:【分治】给定序列A,求\(sigma([l,r]),popcount(Max)==popcount(Min)\)(n<=1e6)

经典分治算法。

点击查看代码


#include<bits/stdc++.h>
using namespace std;
#define _f(i,a,b) for(register int i=a;i<=b;++i)
#define f_(i,a,b) for(register int i=a;i>=b;--i)
#define chu printf
#define ll long long
#define rint register int
#define ull unsigned long long
inline ll re()
{
    ll x=0,h=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')h=-1;
        ch=getchar();
    }
    while(ch<='9'&&ch>='0')
    {
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*h;
}
const int N=1000000+100;
int n;
ll a[N],mx[N],mxp[N],mi[N],mip[N],cnp[N],pop[N];
inline ll solve(int l,int r)
{
    if(l==r)return 1;
    int mid=(l+r)>>1;
    ll Mx=a[mid],Mxp=mid,Mi=a[mid],Mip=mid;
    mx[mid]=Mx,mi[mid]=Mi,mxp[mid]=mid,mip[mid]=mid;
    f_(i,mid-1,l)
    {
        if(a[i]>Mx)
        {
            Mx=a[i];Mxp=i;
        }
        if(a[i]<Mi)
        {
            Mi=a[i];Mip=i;
        }
        mxp[i]=Mxp;mx[i]=Mx;
        mip[i]=Mip;mi[i]=Mi;
    }
    Mx=a[mid+1],Mi=a[mid+1],Mxp=mid+1,Mip=mid+1;
    mxp[mid+1]=mid+1,mip[mid+1]=mid+1;
    mx[mid+1]=a[mid+1];mi[mid+1]=a[mid+1];
    _f(i,mid+2,r)
    {
        if(a[i]>Mx)
        {
            Mx=a[i];Mxp=i;
        }
        if(a[i]<Mi)
        {
            Mi=a[i];Mip=i;
        }
        mxp[i]=Mxp;mx[i]=Mx;
        mip[i]=Mip;mi[i]=Mi;
    }
    int R,L;
    R=mid;
    ll sum=0;
    f_(i,mid,l)
    {
        if(pop[mxp[i]]!=pop[mip[i]])continue;
        while(R<r&&mx[R+1]<=mx[i]&&mi[R+1]>=mi[i])R++;
        sum+=R-(mid+1)+1;
    }
    L=mid+1;
    _f(i,mid+1,r)
    {
        if(pop[mxp[i]]!=pop[mip[i]])continue;
        while(L>l&&mx[L-1]<=mx[i]&&mi[L-1]>=mi[i])L--;
        sum+=mid-L+1;
    }
    R=mid;L=mid+1;
    f_(i,mid,l)//mx在左边,mi在右边
    {
        while(R<r&&mx[R+1]<mx[i])cnp[pop[mip[R+1]]]++,R++;
        while(L<=R&&mi[L]>=mi[i])cnp[pop[mip[L]]]--,L++;
     //  if(l==9&&r==10) chu("mx:%d  contrl:%d--%d\n",i,L,R);
        sum+=cnp[pop[mxp[i]]];
    }
    while(L<=R)cnp[pop[mip[L]]]--,L++;
   // _f(i,0,3)chu("cnp[%d]:%d\n",i,cnp[i]);
    L=mid+1,R=mid;
    _f(i,mid+1,r)
    {
        while(L>l&&mx[L-1]<mx[i])cnp[pop[mip[L-1]]]++,L--;//,chu("  %d++",mip[L]);
        while(L<=R&&mi[R]>=mi[i])cnp[pop[mip[R]]]--,R--;
        sum+=cnp[pop[mxp[i]]];
     //   chu("sumadd:%d\n",cnp[pop[mx[i]]]);
       // chu("%d contrl:%d--%d\n",i,L,R);
    }
    while(L<=R)cnp[pop[mip[L]]]--,L++;
   // _f(i,0,3)chu("cnp[%d]:%d\n",i,cnp[i]);
//  chu("%d--%d:dev:%d\n",l,r,sum);
    return sum+solve(l,mid)+solve(mid+1,r);
}
int main()
{
  // freopen("1.in","r",stdin);
  // freopen("1.out","w",stdout);
  n=re();
  _f(i,1,n)
  {
      a[i]=re();
      ll tmp=a[i];
      while(tmp)
      {
          pop[i]++;
          tmp-=(tmp&(-tmp));
      }
  }
  //_f(i,1,n)chu("pop[%d]:%d\n",i,pop[i]);
  chu("%lld",solve(1,n));
    return 0;
}
/*
10
0 5 7 3 9 10 1 6 13 7
*/

T4【贪心+构造+图的应用】A和B轮流从6n个数里挑选3个连续段,给定A的挑选序列,求一种取拿方案。(n<=200)

一:随便暴力,枚举A和B每次拿出的数。\(O(2n!)\)理论上,但是因为合法方案很多,而且可以随机化搜索顺序,所以可以AK。
用链表优化查找顺序,对于冗余状态直接跳过其实就是大力nxt[pre[i]]=nxt[nxt[nxt[i]],pre[nxt[nxt[nxt[i]]]]=pre[i]......

点击查看代码


#include<bits/stdc++.h>
using namespace std;
#define _f(i,a,b) for(register int i=a;i<=b;++i)
#define f_(i,a,b) for(register int i=a;i>=b;--i)
#define chu printf
#define ll long long
#define rint register int
#define ull unsigned long long
inline ll re()
{
    ll x=0,h=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')h=-1;
        ch=getchar();
    }
    while(ch<='9'&&ch>='0')
    {
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*h;
}
const int N=1200+100;
int n,A[N],has[N],vis[N];
struct Op
{
    int x,y,z;
}e[N];
set<int>s;
set<int>::iterator it;
inline void dfs(int op,int gan)
{
    if(gan==n*2)
    {
        _f(i,1,gan)
        {
            chu("%d %d %d\n",e[i].x,e[i].y,e[i].z);
        }
        exit(0);
    }
   // chu("try:%d %d\n",op,gan);
    int ans[4],tot;
    if(op==1)//该A选了
    {
        int siz=(6*n-gan*3)/3;
        for(int ty=1;ty<=siz;ty++)
        {
          //  chu("siz:%d\n",siz);
            int now=0;int yes=0;tot=0;
            int ok=0;
            for(it=s.begin();it!=s.end();++it)
            {
                int id=*it;
              //  chu("id:%d(has:%d  vis:%d)\n",id,has[id],vis[id]);
                if(has[id]&&!vis[id])
                {
                    ++now;ans[++tot]=id;
                    if(now==3)
                    {
                        ok++;
                        if(ok==ty)
                        {
                            yes=1;break;
                        }
                        else 
                        {
                            now=0;tot=0;
                        }
                    }
                }
                else now=0,tot=0;
            }
           // chu("find?:%d\n",yes);
            if(yes)
            {
                s.erase(ans[1]);
                s.erase(ans[2]);
                s.erase(ans[3]);
                vis[ans[1]]=vis[ans[2]]=vis[ans[3]]=1;
                e[gan+1]=(Op){ans[1],ans[2],ans[3]};
                dfs(!op,gan+1);
                s.insert(ans[1]);
                s.insert(ans[2]);
                s.insert(ans[3]);
                vis[ans[1]]=vis[ans[2]]=vis[ans[3]]=0;
            }
        }

    }
    else
    {
       int siz=(6*n-gan*3)/3;
        for(int ty=siz;ty>=1;ty--)
        {
            int now=0;int yes=0;tot=0;
            int ok=0;
            for(it=s.begin();it!=s.end();++it)
            {
                int id=*it;
                if(!has[id]&&!vis[id])
                {
                    ++now;ans[++tot]=id;
                    if(now==3)
                    {
                        ok++;
                        if(ok==ty)
                        {
                            yes=1;break;
                        }
                        else 
                        {
                            now=0;tot=0;
                        }
                    }
                }
                else now=0,tot=0;
            }
            if(yes)
            {
                s.erase(ans[1]);
                s.erase(ans[2]);
                s.erase(ans[3]);
                vis[ans[1]]=vis[ans[2]]=vis[ans[3]]=1;
                e[gan+1]=(Op){ans[1],ans[2],ans[3]};
                dfs(!op,gan+1);
                s.insert(ans[1]);
                s.insert(ans[2]);
                s.insert(ans[3]);
                vis[ans[1]]=vis[ans[2]]=vis[ans[3]]=0;
            }
        }

    }
}
int main()
{
  // freopen("1.in","r",stdin);
  // freopen("1.out","w",stdout);
    n=re();
    _f(i,1,n*3)
    {
        int x=re();
        has[x]=1;
    }
    _f(i,1,6*n)s.insert(i);
    dfs(1,0);
    return 0;
}
/*
vis[]:B不能拿的牌(A序列+已经拿的)
set<>s:A可以拿的牌(删掉BA已经拿的)
到A拿,不合法的情况:
set里面没有连续段了或者set里面连续段不存在  在A序列里出现过
到B:
set里面没有连续段了或者set里面连续段不存在  没有在A里出现过
如果成功分配:
用三元组记录方案。


2
2 3 4 9 10 11


19 20 21
24 25 26
11 12 13
27 28 29
1 2 3
14 15 16
18 22 23
6 7 8
4 5 9
10 17 30
*/

二:考虑已经完成取拿的序列1--6*n,每个位置的颜色0/1代表是由谁拿的,可以根据取拿的位置限制关系构成括号序列,也即是森林,父亲必须比儿子后拿,儿子拿完父亲才可以拿,实际意义就是([]{}),拿连续的一段,"("必须在"[""}"之后拿。
建立完树林,首先树林的性质就是父亲儿子颜色不一样,同一个儿子颜色一样。
考虑一种拓扑序顺序进行方案构造。有解是需要通过顺序保障的,因为最后一个必须是拿“0”(后手),这个0必须是根而且最后拿,所以可以每次都轮流拿“1”“0”叶子(随时更新),但是只要不是最后一次拿,就不拿剩下的最后一个是0的根,这样一定有解。
怎么理解?
(1)【最后留一个root_0】贪心:尽量拿还是叶子的,这样可以解锁更多的节点,更有可能合法。
(2)【不拿root拿叶子已定有】倒着构造:每次每个人选择一个属于自己的根,这样叶子就是随便选的
也可以举出例子:
1<--0-->1
0<--1-->0
这样的树林如果1先拿根,最后就没0可以选了。

点击查看代码


#include<bits/stdc++.h>
using namespace std;
#define _f(i,a,b) for(register int i=a;i<=b;++i)
#define f_(i,a,b) for(register int i=a;i>=b;--i)
#define chu printf
#define ll long long
#define rint register int
#define ull unsigned long long
inline ll re()
{
    ll x=0,h=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')h=-1;
        ch=getchar();
    }
    while(ch<='9'&&ch>='0')
    {
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*h;
}
const int N=1210;
int id[N],stk[N][3],tot,top,p[N][3],siz[N];
int fa[N],son[N],vis[N],du[N],cor[N],n,se[N],a[N];
int main()
{
  // freopen("1.in","r",stdin);
  // freopen("1.out","w",stdout);
    n=re();
    _f(i,1,3*n)
    {
        a[i]=re();//读入对应的操作数
        se[a[i]]=1;//标记对应数字位置的颜色
    }
    //stk:原编号(球球)
    _f(i,1,6*n)//开始模拟建立树林的过程
    {
      //  chu("rod:%d\n",i);
       // chu("stk[top][0]:%d\n",stk[top][0]);
        if(!top||se[stk[top][0]]!=se[i])
        {
          //  chu("N  ew\n");
            top++;
            siz[top]=0;
            stk[top][siz[top]++]=i;//节点放进去
            id[top]=++tot;//给它编号
        }
        else//连续3个凑
        {
            //chu("insert\n");
            stk[top][siz[top]++]=i;
            if(siz[top]==3)
            {
                fa[id[top]]=id[top-1];
                cor[id[top]]=se[stk[top][0]];
                memcpy(p[id[top]],stk[top],sizeof(p[id[top]]));//把原来的编号都放进去,3个
                top--;//没了
            }
        }
    }
   // chu("tot:%d\n",tot);
    _f(i,1,n<<1)//2*n个节点?
    du[fa[i]]++;//chu("(%d %d %d)cor:%d  fa%d\n",p[i][0],p[i][1],p[i][2],cor[i],fa[i]);
    int _0=0;
    _f(i,1,n<<1)
    if(fa[i]==0&&cor[i]==0)_0++;
    _f(i,1,n<<1)//开始游戏!
    {
       // chu("lef:%d\n",_0);
        int cr=i&1;//应该拿出什么颜色
        int goal=0;
        _f(j,1,tot)//看看哪些可以
        {
           
            //chu("%d %d %d\n",du[j],vis[j],cor[j]);
            if(du[j]==0&&vis[j]==0&&cor[j]==cr)
            {
              //  chu("he will find\n");
                if(i<(n*2)&&cr==0&&_0==1&&fa[j]==0)continue;
             //   chu("he has find\n");
                goal=j;break;
            }
        }
        chu("%d %d %d\n",p[goal][0],p[goal][1],p[goal][2]);
        du[fa[goal]]--;vis[goal]=1;
        if(fa[goal]==0&&cr==0)_0--;//表示根少了一个
    }
    return 0;
}
/*
2
2 3 4 9 10 11

*/
posted on 2022-09-27 21:03  HZOI-曹蓉  阅读(29)  评论(0编辑  收藏  举报