最近做了好多CF的题的说,很多cf的题都很有启发性觉得很有必要总结一下,再加上上次写题解因为太简单被老师骂了,所以这次决定总结一下,也发表一下停课一星期的感想= =
Codeforces 261E Maxim and Calculator
描述:有两个变量a和b,初始值为1和0,每次有两种操作,一个是a=a*b,另一个是b++,求有多少个l<a<r能在p步内达到(p<=100,r<1e9)
首先观察到p最大为100,也就是说最大质因数小于p,打表可得一共大概只有300万个数
考虑dp,设dp[i][j]为当b最多为i时最多须多少次才能a=a*b操作达到j状态,可得f[i][j]=min(f[i-1][j],f[i-1][j/i]+1)
时间复杂度O(np)可以解决这个问题
Code:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define maxn 3000001
#define maxq 101
int f[maxn],p[],id[maxn],n,r,le,num;
bool b[maxn];
int dfs(int x,int y) {
id[++n]=y;
for (int i=x;i<=num;i++) {
if (y*1ll*p[i]>r) break;
dfs(i,y*p[i]);
}
return ;
}
int main(){
int le,k;
// freopen("1.in","r",stdin);
// freopen("1.out","w",stdout);
scanf("%d%d%d",&le,&r,&k);
for (int i=;i<=k;i++) {
if (!b[i]) p[++num]=i;
for (int j=;j<=num&&i*p[j]<=k;j++) {
b[i*p[j]]=;
if (!(i%p[j])) break;
}
}
dfs(,);
f[]=;
for (int i=;i<=n;i++) f[i]=;
sort(id+,id++n);
for (int i=;i<=k;i++) {
int t=;
for (int j=;j<=n;j++) {
while (t<=n&&id[t]!=id[j]*i) ++t;
if (t>n) break;
f[t]=min(f[t],f[j]+);
if ((!b[t])&&(i+f[t]<=k)) b[t]=;
}
}
int ans=;
for (int i=;i<=n;i++){
if (b[i]&&id[i]>=le) ++ans;
}
printf("%d\n",ans);
return ;
}
Codeforces 335F Buy One, Get One Free
描述:有很多物品,每买一个物品可选择价格比它小的一种物品作为赠品,求买下所有物品,使其花费最小(n<=500000)
这道题很难理解,首先,把所有价格相同的东西归在一起,记免费获得第i个东西所获得的利润为f[i],做差得g[i],可得g数组一定是单调递减的(每次肯定选最好的比较好啦),然后考虑如何维护g数组,首先记现在处理的物品价格为x共有y个,当前已有m个物品,那么新加入的值是不会影响前面max(0,min(m/2,m+y/2)-y)的值的(因为我要获得更多的利润肯定先用原来获得利润少的机会),接下来我们考虑什么情况下可以更新。
首先当g[i]<y时一定可以直接替换掉,当g[i]>y时,可能存在一种情况,即我支付g[i]元来换取两个x,即多花一个机会获得 2x-g[i]的机会,这样我们就算出了新的g[i]数组,再维护其单调性即可。
Code:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<set>
using namespace std;
#define maxn 500100
typedef long long ll;
int a[maxn],n,m;
int b[maxn];
typedef pair<int,int> ii;
#define fi first
#define se second
ii s[maxn];
multiset<int> map;
bool cmp(int x,int y){return x>y;}
int main(){
scanf("%d",&n);
for (int i=;i<=n;i++) scanf("%d",a+i);
sort(a+,a++n,cmp);
int l=;
ll ans=;
for (int i=;i<=n;i++) {
if (a[i]!=a[i-]) l++;
s[l].fi=a[i];s[l].se++;
ans+=a[i];
}
n=l;
int size=;
for (int i=;i<=n;i++) {
int x=s[i].fi,y=s[i].se;
int last=size;
size=min(m,(m+y)>>);
int cnt=max(,size-y);
for (int j=size-;j>=cnt;j--)
if (j<map.size()) b[j]=*map.begin(),map.erase(map.begin());
else b[j]=;
for (int j=cnt,k=m-j;j<k&&j<size;j++)
if (b[j]<x) b[j]=x;
else if (--k<size) b[k]=max(,*x-b[j]);
map.insert(b+cnt,b+size);
m+=y;
} for (set<int>::iterator it=map.begin();it!=map.end();it++) {ans-=*it;}
cout<<ans;
return ;
}
Codeforces 293B Distinct Paths
描述:n*m的方格图涂色,已知有若干块以涂色,求涂上k种颜色使所有从左上到右下的路径不经过重复的颜色的方案数(n,m<=1000,k<=10)
其实n,m一定小于k否则无解,但10*10还是太大无法搜索怎么办?我们可以发现,涂到现在还未涂到的颜色本质上还是一样的,所以我们在搜索时遇到还没涂过的颜色只需搜一次即可。
这样还是有几个奇怪的点TLE了,那么我们改变一下搜索策略,从右上搜到左下即可(因为所有颜色都是在一条链上的)
Code:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int b[][],n,m,p,ans,a[][],hash[];
int dfs(int u,int v) {
if (v==m+) return dfs(u+,);
if (u==n+) {++ans;return ;}
int sum=,tmp=;bool flag=;
for (int i=;i<p;i++) {
if (a[u][v]&&a[u][v]!=i+) continue;
if ((b[u-][v]&(<<i))||(b[u][v-]&(<<i))) continue;
hash[i+]++;
b[u][v]=b[u][v-]|b[u-][v]|(<<i);
if (hash[i+]==) {
if (flag) {ans+=tmp;sum+=tmp;}
else {tmp=dfs(u,v+);flag=;sum+=tmp;}
}else sum+=dfs(u,v+);
hash[i+]--;
}
return sum;
}
int main(){
scanf("%d%d%d",&n,&m,&p);
if (n+m->p) {printf("0\n");return ;}
for (int i=;i<=n;i++)
for (int j=;j<=m;j++) {
scanf("%d",a[i]+j);
hash[a[i][j]]++;
}
dfs(,);
printf("%d\n",ans);
return ;
}
Codeforces 251D Two Sets
描述:两人取n个数,使两个人所有数的异或值的和最大的前提下让某个人的异或值最小,求方案(n<100000)
首先我们可以贪心来做,首先求出所有位的奇偶性,对于奇数两个人的配比一定是1,0,而偶的有可能为0,0或1,1,所以我们让大的偶位数尽量为1,在成立的前提下,再尽量使为奇数的位的1在另一个人的身上,这种判断操作都可以通过高斯消元解异或方程组来解决,然后就行了。
Code:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#include<bitset>
using namespace std;
typedef unsigned long long ll;
#define maxn 100100
#define maxk 64
ll c[maxn];
int cnt[maxk];
vector<int> b;
vector<bitset<maxn> > a;
#define pb push_back
int imp[maxn];
int n;
inline void add(bitset<maxn> A,int B) {
int m=a.size();
for (int i=;i<m;i++)
if (A[imp[i]]) A^=a[i],B^=b[i];
int id=-;
for (int i=;i<n;i++) if (A[i]) {id=i;break;}
if (id==-) return ;
imp[m]=id;
for (int i=;i<m;i++)
if (a[i][id]) a[i]^=A,b[i]^=B;
a.pb(A),b.pb(B);
}
int ans[maxn];
int main(){
scanf("%d",&n);
for (int i=;i<n;i++) {
scanf("%llu",&c[i]);
for (int j=;j<;j++) cnt[j]+=(c[i]>>j)&;
}
for (int i=;i>=;i--) {
if (cnt[i]&&!(cnt[i]&)) {
bitset<maxn> t;
t.reset();
for (int j=;j<n;j++) t[j]=(c[j]>>i)&;
add(t,);
}
}
for (int i=;i>=;i--) {
if (cnt[i]&&(cnt[i]&)) {
bitset<maxn> t;
t.reset();
for (int j=;j<n;j++) t[j]=(c[j]>>i)&;
add(t,);
}
}
for (int i=;i<a.size();i++) ans[imp[i]]=b[i];
for (int i=;i<n;i++) printf("%d ",-ans[i]);
return ;
}
Codeforces 319D Have You Ever Heard About the Word?
描述:给定一个字符串,每次找最小的(同时最小则取最左的)形如XX的变为X,求最后的字符串(len<=50000)
考试的时候看成最大的了= =
首先我们可以发现所有删除x的不同长度一定少于sqrt(len)种同时删除长度为l的区间一定不会重复,那么我们可以枚举长度并对所有长度相同的区间一起处理。
具体来说我们每次对于一个区间l,设定len/l个哨兵,判断相邻两个哨兵的最长公共前缀和后缀之和是否超过l,如果有,则说明存在一种长度为l的删法之和在暴力判断哪些需要删除
这些操作用hash就能解决了,总的时间复杂度为O(nsqrt(n))
Code:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 51000
typedef unsigned int uint;
const int base=;
uint h[maxn],pow[maxn];
char s[maxn],st[maxn];
int b[maxn],n,clo;
inline uint hash(int l,int r) {return h[r]-h[l-]*pow[r-l+];}
inline int findf(int l,int r,int x,int y) {
while (l<=r) {
int mid=(l+r)>>;
if (hash(x-mid+,x)==hash(y-mid+,y)) l=mid+;
else r=mid-;
}
return r;
}
inline int findb(int l,int r,int x,int y) {
while (l<=r) {
int mid=(l+r)>>;
if (hash(x,x+mid-)==hash(y,y+mid-)) l=mid+;
else r=mid-;
}
return r;
}
inline bool check(int l) {
for (int i=;i+l<=n;i+=l) {
int f=findf(,l,i,i+l);
int b=findb(,min(n-i-l+,l),i,i+l);
if (f+b->=l) return ;
}
return ;
}
inline void gethash() {for (int i=;i<=n;i++) h[i]=h[i-]*base+s[i]-'a';}
inline void work(int l) {
clo++;
for (int i=;i+*l-<=n;) {
if (hash(i,i+l-)==hash(i+l,i+*l-)) {
for (int j=i;j<=i+l-;j++) b[j]=clo;
i+=l;
}else i++;
}
int cnt=;
for (int i=;i<=n;i++)
if (b[i]!=clo) st[++cnt]=s[i];
for (int i=;i<=cnt;i++) s[i]=st[i];
n=cnt;
s[n+]=;
gethash();
}
int main(){
scanf("%s",s+);
n=strlen(s+);
gethash();
pow[]=;
for (int i=;i<=n;i++) pow[i]=pow[i-]*base;
for (int i=;i<=n/;i++)
if (check(i)) work(i);
printf("%s",s+);
}
Codeforces 280E Sequence Transformation
描述:给定一个非减数列xi要你求出一个数列yi(a<yi-yi-1<b)使sigma(xi-yi)^2最小(n<=300000,xi,yi<q,1<q,a,b<10^9,yi为实数)
这道题真的很精妙,首先我们考虑一个函数fi(x)为当yi=x时的最小开销。然后我们考虑如何由fi-1推到fi
当i-1=1时,可以清楚的看出,为了使其最小,所有的f2(x)中y1的取值必须向f1的极值点靠近,即把f1的极值点左边集体+a,右边集体+b,再加上函数(x2-x)^2。由导数可得,每个函数一定都会有极值点的,因此所有的推法都能这样干。最终答案就是fn的极值点。
那么方案该怎么求呢?我们可以倒过来推,已经知道yn了,那么其他的数都必须尽量靠近fi的极值点,所以我们记录下所有的极值点即可
在实现方面,我们可以用splay直接维护他的导数,3个懒标记即可维护,我的写法足足比其他人少了1/2~~~
比较注意的是极值点可能不在取值范围内,因此边界问题需要比较详细的讨论
(还有一点就是不知为何我的导数并不是连续的,请会的大神告诉我原因QAQ)
Code:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define maxn 300010
struct node{
double x,y,lz,k,lk,lb;
node *ch[],*pre;
node(double _x,double _y,double _k):x(_x),y(_y),k(_k){lk=lb=lz=;pre=ch[]=ch[]=NULL;}
inline void update(){
if (lk||lb) {
k+=lk;y+=lk*x+lb;
if (ch[]) ch[]->lk+=lk,ch[]->lb+=lb+ch[]->lz*lk;
if (ch[]) ch[]->lk+=lk,ch[]->lb+=lb+ch[]->lz*lk;
lk=lb=;
}
if (lz) {
x+=lz;
if (ch[]) ch[]->lz+=lz;
if (ch[]) ch[]->lz+=lz;
lz=;
}
}
inline int d(){return pre->ch[]==this;}
};
inline void rotate(node *u){
node *v=u->pre;
if (v->pre) v->pre->update();
v->update();u->update();
if (v->pre) v->pre->ch[v->d()]=u;
int d=u->d();
u->pre=v->pre;
v->pre=u;
if (u->ch[d^]) u->ch[d^]->pre=v;
v->ch[d]=u->ch[d^];
u->ch[d^]=v;
}
inline void spaly(node *u){u->update();while (u->pre) rotate(u);}
node* search(node *u) {
if (!u) return ;
u->update();
if (u->y>) {
node *ans=search(u->ch[]);
return ans?ans:u;
}
return search(u->ch[]);
}
int cut(node *r,node* &l){
spaly(r);
l=r->ch[];
r->ch[]=;
if (l) l->pre=;
}
node* rest(node *l){
if (!l) return ;
while (l->ch[]) l->update(),l=l->ch[];
l->update();
return l;
}
node* link(node *l,node *r){
if (l==) return r;if (r==) return l;
l=rest(l);
spaly(l);
l->ch[]=r;r->pre=l;
return l;
}
#define inf 1e10
double c[maxn],ans[maxn],w[maxn];
int main(){
int n,q,a,b;
scanf("%d%d%d%d",&n,&q,&a,&b);
for (int i=;i<=n;i++) scanf("%lf\n",c+i);
node *root=new node(q,q*-*c[],);
for (int i=;i<=n;i++) {
node* r=search(root),*l;
cut(r,l);
w[i]=r->x-r->y/r->k;
if (l)w[i]=max(rest(l)->x,w[i]);
if (w[i]>=(i-)*a+) {
l=link(l,new node(w[i],,r->k));r=link(new node(w[i],,),r);
l->lz+=a;r->lz+=b;
root=link(l,r);
root->lk+=;root->lb-=*c[i];
}else {
w[i]=(i-)*a+;
root=link(new node(w[i],,),root);
root->lz+=b;
root->update();
root->lk+=;root->lb-=*c[i];
}
}
node *r=search(root),*l;
cut(r,l);
double x=r->x-r->y/r->k;
if (l) x=max(rest(l)->x,x);
if (x<(n-)*a+) x=(n-)*a+;
if (x>q) x=q;
for (int i=n;i;i--) {
ans[i]=x;
if (x-a<w[i]) x-=a;
else if (x-b>w[i]) x-=b;
else x=w[i];
}
double sum=;
for (int i=;i<=n;i++) {
printf("%.10lf ",ans[i]);sum+=(c[i]-ans[i])*(c[i]-ans[i]);
}
printf("\n%lf\n",sum);
return ;
}
Codeforces 261D Maxim and Increasing Subsequence
描述:计算一个重复t次的数列an的最长上升子序列(n<=1e5,maxa<=1e5,t<=1e9,n*maxa<=2e7)
考试的时候脑残了想不到正解写了个暴力居然a了= =
首先可以发现当t>=maxa时直接输出an中不同元素的个数即可,那么我们考虑t<=maxa的情况。
首先记第i次aj的最长上升子序列为f[j],可以发现随着i的增大f[j]肯定是单调不递减的,那么我们可以考虑f[j]是否能增长即可。考虑维护一个g[i] 为所有f[j]>=i的最小a[j],就可以直接转移并维护了。
Code:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
#define maxn 101000
int b[maxn],a[maxn],f[maxn];
int main(){
int k,n,t,maxb;
scanf("%d%d%d%d",&k,&n,&maxb,&t);
while (k--) {
for (int i=;i<=n;i++) scanf("%d",b+i);
if (t>=maxb) {
sort(b+,b++n);
printf("%d\n",unique(b+,b++n)-b-);
continue;
}
memset(f,,sizeof(f));
memset(a,0x3f,sizeof(a));
a[]=;
for (int i=;i<=t;i++) {
for (int j=;j<=n;j++) {
while (a[f[b[j]]]<b[j]) {a[f[b[j]]]=min(a[f[b[j]]],b[j]);f[b[j]]++;}
a[f[b[j]]]=min(a[f[b[j]]],b[j]);
}
}
int ans=;
for (int i=;i<=maxb;i++) ans=max(ans,f[i]);
printf("%d\n",ans);
}
return ;
}
Codeforces 235D Graph Game
描述:在一个n点n边的图上每次随机删一个点并ans+=当前联通块的大小,递归下去,求ans的期望(n<=3000)
可以记f[i][j]为删掉i点时i与j连通的概率,那么ans=sigma(f[i][j])了(clj太刁了啊这个根本想不到啊啊啊),然后考虑怎么求f[i][j]。
先考虑树的情况,可以得出联通的概率为1/dist(i,j)(因为不在路径上的点删掉与否是无关的,所以只有那dist(i,j)个)是有用的。
若两点路径没经过环同树的情况,否则记环外路径为x,环两侧路径为y,z则答案为1/(x+y)+1/(x+z)+1/(x+y+z)(由容斥原理可得)
N次dfs即可,时间复杂度为O(n^2)
Code:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 4010
struct edges{int to,next;}edge[maxn*];
int next[maxn],l;
inline void addedge(int x,int y){
edge[++l]=(edges){y,next[x]};next[x]=l;
edge[++l]=(edges){x,next[y]};next[y]=l;
}
bool flag;
bool dis[maxn],b[maxn];
int s[maxn],cnt,tot;
int dfs1(int u,int pre) {
b[u]=;
for (int i=next[u];i;i=edge[i].next) {
if (!b[edge[i].to]) {
s[++cnt]=edge[i].to;
dfs1(edge[i].to,u);
if (flag) return ;
cnt--;
}else if (edge[i].to!=pre&&cnt) {
while (cnt&&s[cnt]!=edge[i].to) dis[s[cnt--]]=,tot++;
flag=;
dis[s[cnt]]=;tot++;
}
}
}
double ans=;
int dfs(int u,int dist,int cnt) {
b[u]=;
ans+=1.0/dist;
if (cnt>) {
ans+=1.0/(dist+tot-cnt*+);
ans-=1.0/(dist+tot-cnt);
}
for (int i=next[u];i;i=edge[i].next)
if (!b[edge[i].to]) dfs(edge[i].to,dist+,cnt+dis[edge[i].to]);
}
int main(){
int n;
scanf("%d",&n);
for (int i=;i<=n;i++) {
int x,y;
scanf("%d%d",&x,&y);
x++,y++;
addedge(x,y);
}
s[cnt=]=;
dfs1(,);
memset(b,,sizeof(b));
for (int i=;i<=n;i++) {memset(b,,sizeof(b));dfs(i,,dis[i]);}
printf("%.9lf",ans);
return ;
}
Codeforces 226E More Queries to Array
描述:给定一个数组a以及两种操作:1.将l~r设为x 2.询问l~r中sigma a[i]*(i-l+1)^k (n<1e5,k<=5)
直接把询问拆开来可以发现只需维护a[i]*l的0到5次方即可,线段树维护就可以了
因为一点小小的溢出导致查了好久= =,以后打还是得注意多mod一下
Code:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define maxn 101000
typedef long long ll;
struct node {
int l,r;ll lz,s[];
}t[maxn*];
const ll mod=1000000007ll;
#define lc (x<<1)
#define rc (lc^1)
#define mid ((l+r)>>1)
#define ni3 333333336
#define ni5 400000003
inline ll pow(ll x,int mi) {
if (mi==) return x;
if (mi==) return (+x)*(x)/%mod;
if (mi==) return pow(x,)%mod*(*x+)%mod*ni3%mod;
if (mi==) return pow(x,)*pow(x,)%mod;
if (mi==) return pow(x,)*((x*%mod*x%mod+x*%mod-)%mod)%mod*ni5%mod;
if (mi==) return pow(x,)*((x*%mod*x%mod+x*%mod-)%mod)%mod*ni3%mod;
}
inline ll quick(int l,int r,int mi) {return (pow(r,mi)-pow(l-,mi)+mod)%mod;}
inline void update(int x) {
if (t[x].lz!=-) {
for (int i=;i<=;i++) t[x].s[i]=t[x].lz*quick(t[x].l,t[x].r,i)%mod;
return ;
}
for (int i=;i<=;i++) t[x].s[i]=(t[lc].s[i]+t[rc].s[i])%mod;
}
inline void pushback(int x) {
if (t[x].lz==-) return ;
t[lc].lz=t[rc].lz=t[x].lz;
update(lc);update(rc);
t[x].lz=-;
}
int a[maxn];
void build(int x,int l,int r) {
t[x].l=l,t[x].r=r;t[x].lz=-;
if (l==r) {t[x].lz=a[l];update(x);return ;}
build(lc,l,mid);build(rc,mid+,r);
update(x);
return ;
}
void set(int x,int x1,int y1,int z) {
int l=t[x].l,r=t[x].r;
if (l>y1||r<x1) return ;
if (x1<=l&&r<=y1) {t[x].lz=z;update(x);return;}
pushback(x);
set(lc,x1,y1,z);set(rc,x1,y1,z);
update(x);
return ;
}
ll que(int x,int x1,int y1,int z) {
int l=t[x].l,r=t[x].r;
if (l>y1||r<x1) return ;
if (x1<=l&&r<=y1) return t[x].s[z];
pushback(x);
return (que(lc,x1,y1,z)+que(rc,x1,y1,z))%mod;
}
inline int power(int x,int y){
ll ans=;
for (int i=;i<=y;i++) (ans*=x)%=mod;
return ans;
}
inline ll que(int l,int r,int k) {
int x=-l;
if (k==) return que(,l,r,);
if (k==) return ((que(,l,r,)+que(,l,r,)*power(x,)%mod)%mod+mod)%mod;
if (k==) return ((que(,l,r,)+que(,l,r,)*power(x,)%mod*%mod+que(,l,r,)*power(x,)%mod)%mod+mod)%mod;
if (k==) return ((que(,l,r,)+que(,l,r,)*power(x,)%mod*%mod+que(,l,r,)*power(x,)%mod*%mod+que(,l,r,)*power(x,)%mod)%mod+mod)%mod;
if (k==) return ((que(,l,r,)+que(,l,r,)*power(x,)%mod*%mod+que(,l,r,)*power(x,)%mod*%mod+que(,l,r,)*power(x,)%mod*%mod+que(,l,r,)*power(x,)%mod)%mod+mod)%mod;
if (k==) return ((que(,l,r,)+que(,l,r,)*power(x,)%mod*%mod+que(,l,r,)*power(x,)%mod*%mod+que(,l,r,)*power(x,)%mod*%mod+que(,l,r,)*power(x,)%mod*%mod+que(,l,r,)*power(x,)%mod)%mod+mod)%mod;
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
for (int i=;i<=n;i++) scanf("%d",&a[i]);
build(,,n);
while (m--){
int l,r,x;char opt[];
scanf("%s%d%d%d",opt,&l,&r,&x);
switch(opt[]) {
case '=':
set(,l,r,x);
break;
case '?':
printf("%lld\n",que(l,r,x));
break;
}
}
return ;
}
2000个字刚好= =
总结一下吧,cf还是有很多题特别精妙的,没有像某些省选题那么裸,写完这几道题之后感觉自己整个人都不一样了。还是很推荐去刷这几题的
这次终于特别认真的写了一次题解,自己感觉加深了对题目的认识还是挺不错的,后面还有几道code jam的找机会再来写一下
停课一个星期了,感觉自己整个人都特别的颓废,还是读书比较让人提得起精神,不过既然离省选还有一个月,就应该充分利用这一个月的时间来学习一些东西。
这一季要追6部番= =还是挺累的,不过想弃哪部都舍不得啊,不补旧番了吧
这周末好多比赛啊= =,争取都找时间参加一下吧= =
好了瞎说胡扯完了,改题去了