2022 拉丁美洲区域赛 vp

B(贪心、fft)

将两数列排序后按照正负分离,最大值与最小值类似

考虑求最大值,对于两数列中同号的部分,显然按照绝对值顺序依次相乘;对于异号部分,需要令绝对值乘积尽可能小,简单列式子后可以得到该部分贡献为倒序卷积,按照不同情况翻转其中一个数列

最小值同理,只需先将其中一个数列翻转,后续步骤类似。

#include<bits/stdc++.h>
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;i++)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;i--)
using namespace std;
typedef long long ll;
typedef long double ld;
typedef double db;
typedef vector<int> vi;
const int MAXN=200100;
const int inf=1e9;
int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0',ch=getchar();}
    return x*f;
}
const ld pi=acosl(-1);
int n,a[MAXN],b[MAXN],g[MAXN],h[MAXN];
ll ansmx[MAXN],ansmn[MAXN];
namespace Poly
{
    struct Cd{ld x,y;Cd(ld x=0,ld y=0):x(x),y(y){}};
    Cd operator + (Cd a,Cd b){return Cd(a.x+b.x,a.y+b.y);}
    Cd operator - (Cd a,Cd b){return Cd(a.x-b.x,a.y-b.y);}
    Cd operator * (Cd a,Cd b){return Cd(a.x*b.x-a.y*b.y,a.y*b.x+b.y*a.x);}
    Cd operator / (Cd a,ld b){return Cd(a.x/b,a.y/b);}
    int rev[MAXN<<2];
    int mem(int n)	
    {
        int lg=0,lim=1;for(;lim<n;lim<<=1,lg++);
        rep(i,0,lim-1) rev[i]=(rev[i>>1]>>1)|((i&1)<<(lg-1));
        return lim;
    }
    void fft(Cd *a,int n,int f)
    {
        rep(i,0,n-1) if(i<rev[i]) swap(a[i],a[rev[i]]);
        for(int i=1;i<n;i<<=1)
        {
            Cd wn(cosl(pi/i),f*sinl(pi/i));
            for(int j=0;j<n;j+=i<<1)
            {
                Cd w(1,0),x,y;
                for(int k=0;k<i;k++,w=w*wn)
                x=a[k+j],y=a[k+j+i]*w,a[j+k]=x+y,a[j+k+i]=x-y;
            }
        }
        if(f==1) return ;rep(i,0,n-1) a[i]=a[i]/n;
    }
    void Mul(ll *res,int *a,int n,int *b,int m)
    {
        static Cd A[MAXN<<2],B[MAXN<<2];
        int s=mem(n+m-1);
        rep(i,0,n-1) A[i]=Cd(a[i],0);
        rep(i,0,m-1) B[i]=Cd(b[i],0);
        fill(A+n,A+s,Cd());fill(B+m,B+s,Cd());
        fft(A,s,1);fft(B,s,1);
        rep(i,0,s-1) A[i]=A[i]*B[i];
        fft(A,s,-1);
        rep(i,0,n+m-1) res[i]=(ll)roundl(A[i].x);
    }
}
ll mulres[MAXN<<2];
void solve_max()
{
    rep(i,1,n) a[i]=g[i],b[i]=h[i];
    int l=1,r=n;
    vi res;
    for(;a[l]<0&&b[l]<0;l++) res.push_back(a[l]*b[l]);
    for(;a[r]>0&&b[r]>0;r--) res.push_back(a[r]*b[r]);
    sort(res.begin(),res.end());
    reverse(res.begin(),res.end());
    int tot=0;
    for(auto x:res) ansmx[1+tot]=x+ansmx[tot],tot++;
    if((a[l]==0&&a[r]==0)||(b[l]==0&&b[r]==0)) return ;
    if(b[l]<0||a[r]>0) reverse(b+l,b+r+1);
    else reverse(a+l,a+r+1);
    Poly::Mul(mulres,a+l,r-l+1,b+l,r-l+1);
    rep(i,0,r-l) ansmx[tot+i+1]=ansmx[tot]+mulres[i];
    //rep(i,1,n) cout<<ansmx[i]<<" ";puts("");
}
void solve_min()
{
    rep(i,1,n) a[i]=g[i],b[i]=h[i];
    reverse(b+1,b+n+1);
    int l=1,r=n;
    vi res;
    for(;a[l]<0&&b[l]>0;l++) res.push_back(a[l]*b[l]);
    for(;a[r]>0&&b[r]<0;r--) res.push_back(a[r]*b[r]);
    sort(res.begin(),res.end());
    int tot=0;
    for(auto x:res) ansmn[1+tot]=x+ansmn[tot],tot++;
    if((a[l]==0&&a[r]==0)||(b[l]==0&&b[r]==0)) return ;
    if(a[r]>0||b[l]>0) reverse(b+l,b+r+1);
    else reverse(a+l,a+r+1);
    Poly::Mul(mulres,a+l,r-l+1,b+l,r-l+1);
    rep(i,0,r-l) ansmn[tot+i+1]=ansmn[tot]+mulres[i];
    //rep(i,1,n) cout<<ansmn[i]<<" ";puts("");
}
int main()
{
    n=read();
    rep(i,1,n) g[i]=read();
    rep(i,1,n) h[i]=read();
    sort(g+1,g+n+1);
    sort(h+1,h+n+1);
    solve_max();
    solve_min();
    rep(i,1,n) printf("%lld %lld\n",ansmn[i],ansmx[i]);
}

F(并查集)

由于权值为2的幂次,需要将\(n\)点与其余点尽可能分离,只需在删去\(n\)点后选取包含\(n-1\)点的联通块

实现时在连边时跳过\(n\)点即可

#include<bits/stdc++.h>
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;i++)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;i--)
using namespace std;
typedef long long ll;
typedef long double ld;
typedef double db;
typedef vector<int> vi;
const int MAXN=200100;
const int inf=1e9;
int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0',ch=getchar();}
    return x*f;
}
int n,m,fa[MAXN];
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
int merge(int x,int y)
{
    int f1=find(x),f2=find(y);
    if(f1!=f2) return fa[f1]=f2;
    return 0;
}
int main()
{
    n=read(),m=read();
    rep(i,1,n) fa[i]=i;
    while(m--)
    {
        int a=read(),b=read();
        if(a==n||b==n) continue;
        merge(a,b);
    }
    rep(i,1,n) putchar(find(i)==find(n-1)?'B':'A');
}

G(树哈希)

对所有无根树做树哈希,存在size大小的哈希表里

对每颗树首先枚举因数\(d\),从叶子判断是否可以被划分为若干大小为\(d\)的联通块,对每个块计算哈希值判断是否全部相同,若相同则加上哈希表里该哈希值的个数

#include<bits/stdc++.h>
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;i++)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;i--)
using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef double db;
typedef vector<int> vi;
typedef pair<int,int> pii;
const int MAXN=200100;
const int inf=1e9;
const int mod1=998244353,mod2=1000000009;
int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0',ch=getchar();}
    return x*f;
}
int n,pri[MAXN<<1],tot;
bool ntp[MAXN*15];
void sieve(int n=3e6)
{
    rep(i,2,n)
    {
        if(!ntp[i]) pri[++tot]=i;
        for(int j=1;j<=tot&&i*pri[j]<=n;++j)
            {ntp[i*pri[j]]=1;if(i%pri[j]==0) break;}
    }
}
vi G[MAXN];
vector<pii> trs[MAXN];
int sz[MAXN],Sz,Mx,ctr[2],vis[MAXN];
unordered_map<ull,int> hsh[MAXN];
void getrt(int x,int pa)
{
    int mxs=0;sz[x]=1;
    for(auto v:G[x]) if(v!=pa&&!vis[v])
    {
        getrt(v,x);
        mxs=max(mxs,sz[v]),sz[x]+=sz[v];
    }
    mxs=max(mxs,Sz-sz[x]);
    if(mxs*2<=Sz) ctr[ctr[0]!=0]=x;
}
ull dfs(int x,int pa)
{
    ll v1=1,v2=1;sz[x]=1;
    for(auto v:G[x]) if(v!=pa&&!vis[v])
    {
        auto w=dfs(v,x);
        sz[x]+=sz[v];
        ll a=w>>32,b=w&INT_MAX;
        v1=(a*pri[sz[v]]+v1)%mod1,
        v2=(b*pri[sz[v]]+v2)%mod2;
    }
    //cout<<x<<" "<<v1<<" "<<v2<<endl;
    return (v1<<32)|v2;
}
ull gethash(int tot)
{
    Sz=Mx=tot,ctr[0]=ctr[1]=0;
    getrt(1,0);
    return dfs(ctr[0],0);
}
int flg=0,blksz,ans;
ull v1,v2;
void dfsc(int x,int pa)
{
    sz[x]=1;
    for(auto v:G[x]) if(v^pa)
    {
        dfsc(v,x);
        sz[x]+=sz[v];
    }
    if(sz[x]>blksz) {flg=1;return ;}
    if(sz[x]==blksz)
    {
        vis[pa]=1;
        Sz=Mx=blksz,ctr[0]=ctr[1]=0;
        getrt(x,pa);
        if(!v1)
        {
            v1=dfs(ctr[0],0);
            if(ctr[1]) v2=dfs(ctr[1],0);
        }
        else if(!v2)
        {
            if(ctr[1]||dfs(ctr[0],0)!=v1) flg=1;
        }
        else 
        {
            if(!ctr[1]) flg=1;
            ull w1=dfs(ctr[0],0),w2=dfs(ctr[1],0);
            if((w1!=v1||w2!=v2)&&(w1!=v2||w2!=v1)) flg=1;
        }
        //cout<<"dfsc: "<<x<<" "<<v1<<" "<<v2<<endl;
        if(flg) return ;
        vis[x]=1,vis[pa]=0,sz[x]=0;
    }
}
void check(int tot,int blk)
{
    flg=0,blksz=blk,v1=v2=0;
    rep(i,1,tot) vis[i]=0;
    dfsc(1,0);
    //cout<<"blk: "<<blk<<" "<<flg<<" "<<v1<<" "<<v2<<endl;
    if(flg) return ;
    if(!v2||v1==v2) ans+=hsh[blk][v1];
    else ans+=hsh[blk][v1]+hsh[blk][v2];
}
int main()
{
    sieve();
    n=read();
    rep(i,1,n)
    {
        int m=read(),a,b;
        rep(j,2,m) 
        {
            a=read(),b=read();
            trs[i].emplace_back(a,b);
            G[a].push_back(b),G[b].push_back(a);
        }
        ull w=gethash(m);
        //cout<<m<<" "<<w<<" "<<(w>>32)<<" "<<(w&INT_MAX)<<endl;
        hsh[m][w]++;
        rep(i,1,m) G[i].clear();
    }
    rep(i,1,n)
    {
        int m=trs[i].size()+1;
        for(auto [x,y]:trs[i]) G[x].push_back(y),G[y].push_back(x);
        //cout<<"i: "<<i<<"\n";
        ans=-1;
        rep(blk,1,m) if(m%blk==0)
            check(m,blk);
        rep(i,1,m) G[i].clear();
        printf("%d%c",ans,i==n?'\n':' ');
    }
}

H(KM)

容易算出每个点放在每个位置的贡献,即\(dis[i][j]\),使用KM计算最小匹配即可

#include<bits/stdc++.h>
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;i++)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;i--)
using namespace std;
typedef long long ll;
typedef long double ld;
typedef double db;
typedef vector<int> vi;
typedef pair<int,int> pii;
#define Fill(x,a) memset(x,a,sizeof(x))
const int MAXN=510;
const ll inf=1e18;
int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0',ch=getchar();}
    return x*f;
}
namespace KM
{
    int n,vx[MAXN],vy[MAXN],linky[MAXN],pre[MAXN];
    ll slack[MAXN],dbx[MAXN],dby[MAXN],dis[MAXN][MAXN],ans;
    void bfs(int k)
    {
        int py=0,px,yy=0;ll tmp;
        linky[0]=k;
        Fill(slack,0x3f);Fill(pre,0);
        do
        {
            px=linky[py],tmp=inf,vy[py]=1;
            rep(i,1,n) if(!vy[i])
            {
                if(dbx[px]+dby[i]-dis[px][i]<slack[i])
                    slack[i]=dbx[px]+dby[i]-dis[px][i],pre[i]=py;
                if(slack[i]<tmp) tmp=slack[i],yy=i;
            }
            rep(i,0,n)
                if(vy[i]) dbx[linky[i]]-=tmp,dby[i]+=tmp;
                else slack[i]-=tmp;
            py=yy;
        }while(linky[py]);
        while(py) linky[py]=linky[pre[py]],py=pre[py];
    }
    ll solve()
    {
        Fill(linky,0);rep(i,1,n) {Fill(vy,0);bfs(i);}
        ans=0;rep(i,1,n) ans+=dis[linky[i]][i];
        return ans;
    }
};
int n,e[MAXN][MAXN];
int main()
{
    n=read();KM::n=(n+1)/2;
    rep(i,1,n) rep(j,1,n) e[i][j]=read();
    rep(i,1,(n+1)/2)
    {
        KM::dbx[i]=-inf;
        rep(j,1,(n+1)/2)
            KM::dis[i][j]=-e[i*2-1][j*2-2]-e[i*2-1][j*2],
            KM::dbx[i]=max(KM::dbx[i],KM::dis[i][j]);
    }
    ll ans=KM::solve();
    printf("%lld\n",-ans);
}

I(模拟)

按题意分类模拟

#include<bits/stdc++.h>
using namespace std;
char tmp[111];
int n, dn;
int main()
{
    int i;
    scanf("%s%d", tmp, &n);
    if (tmp[0] == 'M')
    {
        dn = 0;
    }
    else if (tmp[0] == 'T')
    {
        if (tmp[1] == 'u')
        {
            dn = 1;
        }
        else
        {
            dn = 3;
        }
    }
    else if (tmp[0] == 'W')
    {
        dn = 2;
    }
    else if (tmp[0] == 'F')
    {
        dn = 4;
    }
    else if (tmp[1] == 'a')
    {
        dn = 5;
    }
    else
    {
        dn = 6;
    }
    int minans = 100000000;
    for (i=1; i<=n; ++i)
    {
        int t, t1, t2, t3;
        
        scanf("%d", &t);
        {
            t1 = t;
            int predn = (dn - t1%7 + 7) % 7;
            while (predn % 2 == 1 && t1 >= 30)
            {
                predn += 2;
                t1 -= 30;
                if (predn == 5)
                {
                    t1 -= 2;
                    predn = 0;
                    break;
                }
            }
            if (t1 >= 0)
            {
                t1 %= 91;
            }
            while (t1 >= 30)
            {
                predn = (predn + 2)% 7;
                t1 -= 30;
                if (predn == 6)
                {
                    t1 -= 1;
                    predn = 0;
                }
            }
        }
        if (t1 < 0)
        {
            t3 = - t1;
        }
        else
        {
            t3 = (t1 == 0 && t != 0) ? 0 : 30 - t1;
            t2 = dn + t3;
            if (t2 %7 == 5)	t3 += 2;
            else if (t2 %7 == 6)	t3 += 1;
        }
        minans = min(minans, t3);
    }
    printf("%d\n", minans);
    return 0;
}

J(栈)

容易发现仅有两端点都在边界上的点对才有意义,否则均可以绕边框

相当于在环上不能存在\(ABAB\)型的点对,随意找一个起点check即可

#include<bits/stdc++.h>
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;i++)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;i--)
using namespace std;
typedef long long ll;
typedef long double ld;
typedef double db;
typedef vector<int> vi;
typedef pair<int,int> pii;
const int MAXN=200100;
const int inf=1e9;
int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0',ch=getchar();}
    return x*f;
}
int w,h,n,tot,tp,st[MAXN];
pii g[MAXN];
int calc(int x,int y)
{
    if(x==0&&y>=0) return y+1;
    if(y==h&&x>=0) return x+h+1;
    if(x==w) return h+1+w+(h-y);
    if(y==0) return h*2+w+1+(w-x);
    return 0;
}
int main()
{
    w=read(),h=read(),n=read();
    rep(i,1,n)
    {
        int x=read(),y=read(),a=read(),b=read();
        int l=calc(x,y),r=calc(a,b);
        if(l*r==0) continue;
        if(l>r) swap(l,r);
        g[++tot]={l,i};
        g[++tot]={r,-i};
        //cout<<l<<" "<<r<<endl;
    }
    sort(g+1,g+tot+1);
    rep(i,1,tot)
    {
        if(g[i].second<0)
        {
            if(tp&&st[tp]==-g[i].second) tp--;
            else st[++tp]=g[i].second;
        }
        else 
        {
            st[++tp]=g[i].second;
        }
    }
    puts(tp>0?"N":"Y");
}

K(签到)

签到

#include<bits/stdc++.h>
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;i++)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;i--)
using namespace std;
typedef long long ll;
typedef long double ld;
typedef double db;
typedef vector<int> vi;
const int Maxn=1000005;
const int inf=1e9;
int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0',ch=getchar();}
    return x*f;
}
int n;
char ssr[Maxn];
int cnt[Maxn];
int tot;
int main() {
    n=read();
    for(int i=1;i<=n;++i) {
        
        scanf("%s",ssr);
        int len=strlen(ssr);
        tot|=(1<<(ssr[0]-'A'));
        
        for(int j=0;j<len;++j) {
            
            cnt[i]|=(1<<(ssr[j]-'A'));
            
        }
    }
    
    int flag=0;
    for(int i=1;i<=n;++i) {
        
        if((cnt[i]&tot)==cnt[i]) {
            flag=1; break;
        }
    }
    
    if(flag) cout<<"Y";
    else cout<<"N";
    
}

L(期望)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const ll md = 1e9+7;
ll poww(ll a, ll b)
{
    ll ans = 1;
    for (; b; b>>=1, a=a*a%md)
        if (b&1)
            ans = ans*a%md;
    return ans;
}
#define inv(x) (poww((x), md-2))
const int N = 2000000;

ll fac[N+5], ifac[N+5], pw2[N+5];
ll C(ll n, ll m)
{
    return fac[n] * ifac[m] %md *ifac[n-m] %md;
}


ll calc(ll g, ll g1, ll g0, ll e, ll l)
{
    ll ans = g;
    ll t;
    
    t = min(e, g1);
    e -= t;
    g1 -= t;
    ans += t;
    
    t = e / 2 * 2;
    e -= t;
    g0 -= t/2;
    ans += t;
    
    //e=0/1
    if (e == 1)
    {
        --g0;
    }
    
    ll g1_l = 0;
    t = min(g0, l);
    l -= t;
    g1_l += t;
    
    if (e == 1 && l >= 1)
    {
        --l;
        --e;
        ++ans;
    }
    
    t = min(g1, l);
    l -= t;
    
    g1_l -= l;
    ans += g1_l;
    
    return ans;
    
}
ll n, g, l, e;
int main()
{
    int i;
    fac[0] = 1;
    for (i=1; i<=N; ++i)
    {
        fac[i] = fac[i-1] *i %md;
    }
    ifac[N] = inv(fac[N]);
    for (i=N; i>=1; --i)
    {
        ifac[i-1] = ifac[i] *i %md;
    }
    pw2[0]=1;
    for (i=1; i<=N; ++i)
    {
        pw2[i] = pw2[i-1] *2 %md;
    }
    //printf("%lld %lld %lld\n", ifac[0], ifac[1], ifac[2]);
    scanf("%lld%lld%lld%lld", &n, &g, &l, &e);
    if (2*n <= g)
    {
        g = 2*n;
        l=e=0;
    }
    else if (2*n <= g+e)
    {
        e = 2*n-g;
        l=0;
    }
    else if (2*n <= g+e+l)
    {
        l = 2*n-g-e;
    }
    ll ans = 0;
    ll invall = inv(C(2*n, g));
    for (i=0; i<=g/2; ++i)
    {
        if (n<i || n-i < g-2*i )	continue;
        ll t1 = C(n, i)*C(n-i,g-2*i)%md*pw2[g-2*i]%md*invall%md;
        ll t2 = calc(g, g-2*i, n-g+i, e, l);
        ans = (ans + t1 * t2 ) %md;
        //printf("--%d %lld %lld %lld %lld\n", i, g-2*i, n-g+i, t1, t2);
    }
    printf("%lld\n", ans);
    return 0;
}

M(贪心)

\(ddl\)升序排序后check合法性,在合法情况下逐位判断能否交换使字典序最小

预处理信息使得可以\(O(1)\)怕判断能否交换

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int Maxn=5005,Inf=0x3f3f3f3f;
int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0',ch=getchar();}
    return x*f;
}
int n;

struct Task {
    int t,d,i;
} task[Maxn];
inline bool cmp(const Task &A,const Task &B) {
    return A.d<B.d;
}

ll sumt[Maxn];

int sub[Maxn],minsub[Maxn],pos[Maxn];

int used[Maxn],ans[Maxn];

int main() {
    n=read();
    
    for(int i=1;i<=n;++i) {
        int t=read(),d=read();
        task[i]=(Task){t,d,i};
    }
    sort(task+1,task+1+n,cmp);
    
    minsub[0]=Inf;
    for(int i=1;i<=n;++i) {
        
        sumt[i]=sumt[i-1]+task[i].t;
        if(sumt[i]>task[i].d) {
            cout<<"*";
            exit(0);
        }
        
        sub[i]=task[i].d-sumt[i];
        minsub[i]=min(minsub[i-1],sub[i]);
        pos[task[i].i]=i;
        
        
    }
    
    for(int i=1;i<=n;++i) {
        
        for(int k=1;k<=n;++k) {
            
            if(used[k]) continue;
            
            int cur=pos[k];
            
            if(minsub[cur-1]>=task[cur].t) {
                
                Task temp=task[cur];
                
                for(int t=cur;t>i;--t)
                    task[t]=task[t-1];
                task[i]=temp;
                
                used[k]=1;
                break;
            }
            
            
        }
        
        for(int k=1;k<=n;++k) {
            sumt[k]=sumt[k-1]+task[k].t;
            
            sub[k]=task[k].d-sumt[k];
            if(k<=i) sub[k]=Inf;
            minsub[k]=min(minsub[k-1],sub[k]);
            pos[task[k].i]=k;

        }
    }
    
    for(int i=1;i<=n;++i) 
        cout<<task[i].i<<" ";
    
    return 0;
}
posted @ 2022-10-27 17:31  jack_yyc  阅读(48)  评论(0编辑  收藏  举报