部分题解乱写

csps模拟测试 75

T2 炼金术士的疑惑

可能不算一道很思维的题?但把信息学运用到了实践,话说谁在现实中会列一个200个物质的化学方程式

显然是高斯消元,但有自由元。我们要求的是一个方程,也就是说除此以外都和我们无关。

题目保证有解,暗示我们去用已知信息去获得未知信息。似乎可以得出来,用每个方程去消掉最后方程的元?

我们最终一定可以得到

部分题解乱写_第1张图片

 

然后一个一个消就A了。

 

T3 老司机的狂欢

好题,考试的时候没有给太多时间,也没有发现就是一个$LIS$。

老司机们的相对位置不变也就是说所选的k个人的末位置与初位置相同,我们以初位置为下标,就是一个$LIS$。

只要二分然后求个$LIS$就行了,时间复杂度$O(nlogn^2)$

第二问很好,构造方案是把转移看成一棵树,也就是$i$只由$j$转移过来。

那么到底由谁转移过来?某个节点的字典序就是其到根的路径,对于$j_1$和$j_2$,$j_1$和$j_2$的$lca$处以上是一样的,我们只关心$lca$以下的,又因为字典序只关心最小的,我们找$min$就行了,这个可以倍增求,然后用树状数组弄就行了。也是$O(nlogn^2)$

ps:倍增一定要到0!!!!

 

  1 #include
  2 #include
  3 #include
  4 #include
  5 #include
  6 #define int long long
  7 using namespace std;
  8 const int N=1e5+5;
  9 struct node{
 10     int a,x,id;
 11     inline void init(){scanf("%lld%lld",&x,&a);return ;}
 12     int calc(int tim)
 13     {
 14         return x*2+a*tim*tim;
 15     }
 16     friend bool operator < (const node a,const node b)
 17     {
 18         return a.x<b.x;
 19     }
 20 }a[N];
 21 int t[N],n,fa[N][21],mn[N][21],k,f[N],tot;
 22 struct pre{
 23     int query(int pos)
 24     {
 25         int ans=0;
 26         for(int i=pos;i;i-=i&-i) ans=max(ans,t[i]);
 27         return ans;
 28     }
 29     void insert(int pos,int val)
 30     {
 31         for(int i=pos;i<=tot;i+=i&-i) t[i]=max(val,t[i]);
 32         return ;
 33     }
 34 }T;
 35 int gmin(int x,int y)
 36 {
 37     if(!x||!y) return x|y;
 38     int xx=x,yy=y;
 39     int mna=a[x].id,mnb=a[y].id;
 40     for(int i=20;~i;i--)
 41         if(fa[x][i]!=fa[y][i]) mna=min(mna,mn[x][i]),mnb=min(mnb,mn[y][i]),x=fa[x][i],y=fa[y][i];
 42     return mnaxx:yy;
 43 }
 44 int query(int pos)
 45 {
 46     if(!pos) return 0;
 47     int ans=0;
 48     for(int i=pos;i;i-=i&-i)
 49     {
 50         if(f[t[i]]>f[ans]) ans=t[i];
 51         else if(f[t[i]]==f[ans]) ans=gmin(ans,t[i]);
 52     }
 53     return ans;
 54 }
 55 void insert(int pos,int id)
 56 {
 57     for(int i=pos;i<=tot;i+=i&-i) 
 58     {
 59         if(f[id]>f[t[i]]) t[i]=id;
 60         else if(f[id]==f[t[i]]) t[i]=gmin(id,t[i]);
 61     }
 62     return ;
 63 }
 64 long long b[N];
 65 int tmp[N],s[N],top;
 66 int check(int tim)
 67 {
 68     memset(t,0,sizeof t);
 69     int ans=0;
 70     for(int i=1;i<=n;i++) b[i]=a[i].calc(tim);
 71     sort(b+1,b+n+1);tot=unique(b+1,b+n+1)-b-1;
 72     for(int i=1;i<=n;i++) tmp[i]=lower_bound(b+1,b+tot+1,a[i].calc(tim))-b;
 73     for(int i=1;i<=n;i++)
 74         f[i]=T.query(tmp[i]-1)+1,T.insert(tmp[i],f[i]),ans=max(ans,f[i]);
 75     return ans;
 76 }
 77 signed main()
 78 {
 79     scanf("%lld%lld",&n,&k);
 80     for(int i=1;i<=n;i++) a[i].init(),a[i].id=i;
 81     sort(a+1,a+n+1);
 82     int l=0,r=86400,ans=0,ed=0;
 83     while(l<=r)
 84     {
 85         int mid=l+r>>1;
 86         if(check(mid)>=k) l=mid+1,ans=mid;
 87         else r=mid-1;
 88     }
 89     memset(mn,0x3f,sizeof mn);
 90     cout<endl;
 91     if(check(ans)>k) return puts("-1"),0;
 92     memset(t,0,sizeof t);memset(f,0,sizeof f);
 93     for(int i=1;i<=n;i++) b[i]=a[i].calc(ans);
 94     sort(b+1,b+n+1);tot=unique(b+1,b+n+1)-b-1;
 95     for(int i=1;i<=n;i++) tmp[i]=lower_bound(b+1,b+tot+1,a[i].calc(ans))-b;
 96     a[0].id=0x7f7f7f7f;
 97     for(int i=1;i<=n;i++)
 98     {
 99         fa[i][0]=query(tmp[i]-1),f[i]=f[fa[i][0]]+1,mn[i][0]=a[fa[i][0]].id;
100         for(int j=1;j<=20;j++)
101         {
102             fa[i][j]=fa[fa[i][j-1]][j-1];
103             mn[i][j]=min(mn[i][j-1],mn[fa[i][j-1]][j-1]);
104         }
105         insert(tmp[i],i);
106         if(f[i]==k) ed=gmin(ed,i);
107     }
108     while(ed) s[++top]=a[ed].id,ed=fa[ed][0];
109     sort(s+1,s+top+1);
110     for(int i=1;i<=k;i++) cout<endl;
111     return 0;
112 }
View Code

 

 

 

csps模拟测试 74

垃圾kx被卡常联赛就退役了,就滚回去学高考课了。

T2 玩具

又是神题。

部分分打法:这颗树上点的深度是连续的,也即:其差分数组只有0/1,我们就把状态压缩成$2^n$,就可以枚举直接转移了。

复杂度$O(2^nn)$

先设一个数组$f[i][j]$表示由$i$个节点构成的树深度为$j$的概率,发现不好转移。改变定义设$f[i][j]$表示由$i$个节点构成树的深度小于等于$j$的概率,最后直接是$(f[i][j]-f[i][j-1])*j$。考虑如何维护,我们每新加一个点,都会有/没有深度的变化,我们无法记录每一层的状态,所以考虑以新加的节点为新的根。也就是它的子树们本来是森林,这启发我们再开一个辅助数组$g[i][j]$来表示由$i$个节点构成森林深度小于等于$j$的概率。易得:$f[i][j]=g[i-1][j-1]$

那么怎么维护$g$数组?我们可以局部枚举第一棵树的节点个数也就是$f[k][j]*g[i-k][j]$,但这样是不对的。因为这样枚举了所有某一个子树大小为$k$且总结点个数为$i$的森林,我们需要把$f$所表示的树强制为第一棵树。设$dp[i][j]$表示$i$个节点组成的森林里第一棵子树大小为$j$的概率,枚举第$i$棵的位置简单递推就行了。时间复杂度$O(n^3)$

 

 1 #include
 2 #include
 3 #define int long long
 4 #define F(i,a,b) for(register int i=(a);i<=(b);++i)
 5 using namespace std;
 6 const int N=205;
 7 int dp[N][N],f[N][N],g[N][N],inv[N];
 8 signed main()
 9 {
10     int n,p,ans=0; scanf("%lld%lld",&n,&p); inv[1]=dp[1][1]=1;
11     F(i,2,n) inv[i]=(p-inv[p%i]*(p/i)%p)%p;
12     F(i,2,n) F(j,1,i) dp[i][j]=(dp[i-1][j-1]*(j-1)%p*inv[i]%p+dp[i-1][j]*(i-j)%p*inv[i]%p)%p;
13     F(i,0,n) g[0][i]=f[1][i]=1;
14     F(i,1,n) F(j,0,i) {
15             if(j^0) f[i][j]=g[i-1][j-1];
16             F(k,0,i) (g[i][j]+=f[k][min(j,k)]*g[i-k][min(i-k,j)]%p*dp[i][k]%p)%=p;
17     }
18     F(i,1,n-1) (ans+=(f[n][i]-f[n][i-1])*i%p)%=p;
19     printf("%lld\n",(ans%p+p)%p); 
20     return 0;
21 }
View Code

 

 

 

csps模拟测试 73

T3 小P的生成树

好神啊,不过随机化水过了。

我考场上2h没有打出来搜索,很自闭。

这个搜索是我想麻烦了,在图里直接搜一棵树不可行,枚举边选不选。

至于优化,首先冰茶几要按秩合并,其次我们构造一个估价函数$g[i][j]$表示选$i~m$条边构造出来j条边的最大价值。

这里用到了$|a+b|\leqslant |a|+|b|$的性质而跑的最小生成树。

 1 #include
 2 #define LL long long
 3 #define N 55
 4 #define M 205
 5 #define ci const int
 6 #define F(i,a,b) for(register int i=a;i<=b;++i)
 7 using namespace std;
 8 double ans;
 9 int f[N],sz[N],n,m,tmp[M],fn[N],g[M][M];
10 struct EDGE{
11     int a,b,st,ed,w;
12     friend bool operator < (const EDGE x,const EDGE y)
13     {
14         return x.w>y.w;
15     }
16 }E[10005],F[10005];
17 int find(ci x)
18 {
19     if(f[x]==x) return x;
20     return find(f[x]);
21 }
22 int findx(ci x)
23 {
24     if(fn[x]==x) return x;
25     return fn[x]=find(fn[x]);
26 }
27 inline void pre()
28 {
29     F(i,1,n) f[i]=i,sz[i]=1;
30     return ;
31 }
32 int calc(int pos)
33 {
34     int j=1,tmp=0,cnt=0;
35     for(int i=pos;i<=m;i++,j++) F[j]=E[i];
36     sort(F+1,F+j);
37     for(int i=1;i<=n;i++) fn[i]=i;
38     for(int i=1;i)
39     {
40         int fa=findx(F[i].st),fb=findx(F[i].ed);
41         if(fa==fb) continue;
42         fn[fa]=fb;
43         tmp+=F[i].w;
44         g[pos][++cnt]=tmp;
45     }
46     return tmp;
47 }
48 void dfs(int pos,int num,int nowa,int nowb)
49 {
50     if(num==n-1)
51     {
52         ans=max(ans,sqrt(nowa*nowa+nowb*nowb));
53         return ;
54     }
55     if(sqrt(nowa*nowa+nowb*nowb)+g[pos][n-1-num]<=ans) return ;
56     if(pos==m+1) return ;
57     int fa=find(E[pos].st),fb=find(E[pos].ed),tmp;
58     if(fa!=fb)
59     {
60         if(sz[fa]<sz[fb])
61         {
62             f[fa]=fb,sz[fb]+=sz[fa];
63             dfs(pos+1,num+1,nowa+E[pos].a,nowb+E[pos].b);
64             f[fa]=fa,sz[fb]-=sz[fa];
65         }
66         else 
67         {
68             f[fb]=fa,sz[fa]+=sz[fb];
69             dfs(pos+1,num+1,nowa+E[pos].a,nowb+E[pos].b);
70             f[fb]=fb,sz[fa]-=sz[fb];
71         }
72     }
73     dfs(pos+1,num,nowa,nowb);
74 }
75 int main()
76 {
77     scanf("%d%d",&n,&m);
78     if(n>12) return 0;
79     pre();
80     F(i,1,m)
81     {
82         tmp[i]=i;
83         int a,b,c,d;
84         scanf("%d%d%d%d",&a,&b,&c,&d);
85         E[i]=(EDGE){c,d,a,b,abs(c)+abs(d)};
86     }
87     F(i,1,m) swap(E[i],E[tmp[i]]),calc(i);
88     dfs(1,0,0,0);
89     printf("%.6lf\n",ans);
90     return 0;
91 }
View Code

 其实分析向量的性质,会发现求和是映射到某个向量上,然后我们就可以枚举最终映射的角度。

直接枚举会T掉

最小/大生成树只与相对大小有关

所以我们可以枚举两两向量之间大小比较,那我们就把圆分成了$m^2$个区间,每个区间内生成树的边相对大小相同。

也就是说同一区间内的最大生成树是一样的,枚举区间,取max就行了。复杂度$O(m^3logm)$

但我打的随机化。

 1 #include
 2 using namespace std;
 3 int head[55],cnt;
 4 int to[405],nxt[405],a[405],b[405],n,m,tot,nowa,nowb,f[55];
 5 double ans,kx,tdcp;
 6 int find(int x) {if(f[x]==x) return x;return f[x]=find(f[x]);}
 7 inline void merge(int a,int b)
 8 {
 9     int fa=find(a),fb=find(b);
10     f[fa]=fb;
11 }
12 inline void Add(int u,int v,int x,int y)
13 {
14     to[++cnt]=v,nxt[cnt]=head[u];
15     head[u]=cnt,a[cnt]=x,b[cnt]=y;
16 }
17 struct EDGE{
18     int a,b,st,ed;
19 }E[10005];
20 bool cmp(const EDGE x,const EDGE y)
21 {
22     return x.a*kx+x.b*tdcptdcp;
23 }
24 int main()
25 {
26     srand(1000000007);
27     scanf("%d%d",&n,&m);
28     for(int i=1;i<=m;i++)
29     {
30         int a,b,c,d;
31         scanf("%d%d%d%d",&a,&b,&c,&d);
32         Add(a,b,c,d),Add(b,a,c,d);
33         E[i]=(EDGE){c,d,a,b};
34     }
35     int tim=300;
36     while(tim--)
37     {
38         double tmp=0,tmpx=0;
39         kx=1.0*(rand()-1000000000)/1000000;
40         tdcp=1.0*(rand()-1000000000)/1000000;
41         sort(E+1,E+m+1,cmp);
42         for(int i=1;i<=n;i++) f[i]=i;
43         for(int i=1;i<=m;i++)
44         {
45             if(find(E[i].st)==find(E[i].ed)) continue;
46             merge(E[i].st,E[i].ed);
47             tmp+=E[i].a,tmpx+=E[i].b;
48         }
49         ans=max(ans,sqrt(tmp*tmp+tmpx*tmpx));
50     }
51     printf("%.6lf\n",ans);
52     return 0;
53 }
View Code

 

csps模拟测试 72

T2 简单的期望

神DP,%%%%%$MouDing$ && $mikufun$

很难处理的是进位 问题转化:每次<<1或+1,求最后的末尾连续0的期望
<<1的贡献很好统计,+1会进位,不好统计,由于每次加的数很小,所以暴力枚举后8位,保证一定不会进位两次
这样对于第九位的贡献就显然了。
主要思想:压缩状态,只考虑难处理的进位操作,有效利用所有有用的状态

 1 /*
 2     问题转化:每次<<1或+1,求最后的末尾连续0的期望
 3     <<1的贡献很好统计,+1会进位,不好统计,由于每次加的数很小,所以暴力枚举后8位,保证一定不会进位两次
 4     这样对于第九位的贡献就显然了。
 5     主要思想:压缩状态,只考虑难处理的进位操作
 6 */
 7 #include
 8 #include
 9 using namespace std;
10 const int lmt=(1<<8)-1;
11 double dp[205][1<<8][245][2];
12 int x,n;
13 double p,ans;
14 int main()
15 {
16     cin>>x>>n>>p;p/=100;
17     int res=x&lmt,opt=(x>>8)&1,cnt=0;
18     for(int i=9;(((x>>i)&1)==opt)&&(1<);
19     dp[0][res][cnt][opt]=1;
20     for(int i=0;i)
21         for(int j=0;j<=lmt;j++)
22             for(int k=0;k<=n+30;k++)
23             {
24                 if((j>>7)&1)
25                 {
26                     dp[i+1][(j<<1)&lmt][k+1][1]+=dp[i][j][k][1]*p;
27                     dp[i+1][(j<<1)&lmt][0][1]+=dp[i][j][k][0]*p;
28                 }
29                 else 
30                 {
31                     dp[i+1][(j<<1)&lmt][k+1][0]+=dp[i][j][k][0]*p;
32                     dp[i+1][(j<<1)&lmt][0][0]+=dp[i][j][k][1]*p;
33                 }
34                 if(j==255)
35                 {
36                     dp[i+1][0][0][1]+=dp[i][j][k][0]*(1-p);
37                     dp[i+1][0][k][0]+=dp[i][j][k][1]*(1-p);
38                 }
39                 else 
40                 {
41                     dp[i+1][j+1][k][0]+=dp[i][j][k][0]*(1-p);
42                     dp[i+1][j+1][k][1]+=dp[i][j][k][1]*(1-p);
43                 }
44             }
45     for(int i=0;i<=lmt;i++)
46         for(int k=0;k<=n+30;k++)
47         {
48             int cnt=0;
49             for(int j=i;j&&(!(j&1));cnt++,j>>=1);
50             if(!i) ans+=dp[n][i][k][1]*8,ans+=dp[n][i][k][0]*(9+k);
51             else ans+=(dp[n][i][k][1]+dp[n][i][k][0])*cnt;
52         }
53     printf("%.10lf\n",ans);
54     return 0;
55 }
View Code

 

 

T3 简单的操作

主要想说一下我和正解的差距。

结论我想到了:联通块里一定是一个二分图。

但是我:Tarjan+黑白染色+树P

正解:黑白染色+bfs

我的思路有偏差,没有想到对环的具体处理,但是代码实现没有问题。

思考不够全面,不能YY,要认真的去挖掘。

还有:考试我手模了能$hack$掉我代码的数据,但是我按照我代码的思路去想这个数据,认为他是对的。

不要被代码左右了思想。

考试代码:

  1 /*
  2     不存在三个点可以相互到达且直接连边即该环一定是一个二分图的形式
  3     Tarjan,判是不是二分图黑白染色
  4     然后变成一棵树,最长链就行
  5 */
  6 #include
  7 using namespace std;
  8 const int N=2e5+5,M=2e5+5;
  9 int head[N],to[M<<1],nxt[M<<1],cnt,dfn[N],bl[N],s[N],top,low[N],def[N];
 10 char v[N],col[N],in_s[N],tot,num,MAXN,vst[N];
 11 int st[M],ed[M],d[N],tmp;
 12 inline void Add(int u,int v)
 13 {
 14     to[++cnt]=v;
 15     nxt[cnt]=head[u];
 16     head[u]=cnt;
 17 }
 18 void dfs(int x)
 19 {
 20     def[x]=bl[x]*2+col[x];//重定义编号
 21     for(int i=head[x];i;i=nxt[i])
 22     {
 23         int y=to[i];
 24         if(bl[y]!=bl[x]) //不同块(两个强联通分量之间只有一条边,所以不会出现差错(吧))
 25         {
 26             if(!col[y])
 27             {
 28                 col[y]=2;
 29                 dfs(y);
 30             }
 31             continue;
 32         }
 33         if(!col[y])
 34         {
 35             col[y]=col[x]^1;//染色
 36             dfs(y);
 37         }
 38         else if(col[y]==col[x])//无解
 39         {
 40             puts("-1");
 41             exit(0);
 42         }
 43     }
 44 }
 45 void Tarjan(int x,int fa)
 46 {
 47     dfn[x]=low[x]=++tot;s[++top]=x;in_s[x]=1;
 48     for(int i=head[x];i;i=nxt[i])
 49     {
 50         int y=to[i];
 51         if(y==fa) continue;
 52         if(!dfn[y])
 53         {
 54             Tarjan(y,x);
 55             low[x]=min(low[x],low[y]);
 56         }
 57         else if(in_s[y]) low[x]=min(low[x],dfn[y]);
 58     }
 59     if(dfn[x]==low[x])
 60     {
 61         ++num;
 62         while(top)
 63         {
 64             int t=s[top];
 65             bl[t]=num;
 66             in_s[t]=0;
 67             top--;
 68             if(t==x) break;
 69         }
 70     }
 71 }
 72 void dp(int x)//(会有重边!!!)
 73 {
 74     vst[x]=1;
 75     int fir=0,sec=0;
 76     for(int i=head[x];i;i=nxt[i])
 77     {
 78         int y=to[i];
 79         if(vst[y]) continue;
 80         dp(y);
 81         if(d[y]+1>fir) sec=fir,fir=d[y]+1;
 82         else if(d[y]+1>sec) sec=d[y]+1;
 83     }
 84     tmp=max(tmp,fir+sec);
 85     d[x]=fir;
 86     return ;
 87 }
 88 int main()
 89 {
 90     int n,m,js=0,ans=0;
 91     scanf("%d%d",&n,&m);
 92     for(int i=1;i<=m;i++)
 93     {
 94         scanf("%d%d",&st[i],&ed[i]);
 95         Add(st[i],ed[i]),Add(ed[i],st[i]);
 96     }
 97     for(int i=1;i<=n;i++) 
 98     {
 99         if(!dfn[i]) 
100         Tarjan(i,0),col[i]=2,dfs(i);
101     }
102     memset(head,0,sizeof head),cnt=0;
103     for(int i=1;i<=m;i++)
104     {
105         if(def[st[i]]==def[ed[i]]) continue;
106         Add(def[st[i]],def[ed[i]]);
107         Add(def[ed[i]],def[st[i]]);
108     }
109     for(int i=1;i<=n;i++)
110     {
111         if(!vst[def[i]]) 
112         {
113             tmp=0;
114             dp(def[i]);
115             if(tmp)
116             {
117                 ans+=tmp;
118                 js++;
119             }
120         }
121     }
122     cout<endl;
123 }
View Code

 

AC代码:

 1 #include
 2 using namespace std;
 3 const int N=1e3+5,M=2e5+5;
 4 int head[N],to[M<<1],nxt[M<<1],cnt;
 5 int d[N][N],tmp;
 6 char col[N];
 7 inline void Add(int u,int v)
 8 {
 9     to[++cnt]=v;
10     nxt[cnt]=head[u];
11     head[u]=cnt;
12 }
13 inline void BFS(int st)
14 {
15     queue<int>Q;
16     Q.push(st);
17     while(Q.size())
18     {
19         int x=Q.front();Q.pop();
20         tmp=max(tmp,d[st][x]);
21         for(register int i=head[x];i;i=nxt[i])
22         {
23             int y=to[i];
24             if(!d[st][y]&&y!=st)
25                 d[st][y]=d[st][x]+1,Q.push(y);
26         }
27     }
28 }
29 void dfs(int x)
30 {
31     BFS(x);
32     for(int i=head[x];i;i=nxt[i])
33     {
34         int y=to[i];
35         if(!col[y])
36         {
37             col[y]=col[x]^1;//染色
38             dfs(y);
39         }
40         else if(col[y]==col[x])//无解
41         {
42             puts("-1");
43             exit(0);
44         }
45     }
46 }
47 int main()
48 {
49     int n,m,js=0,ans=0;
50     scanf("%d%d",&n,&m);
51     for(int i=1,a,b;i<=m;i++)
52         scanf("%d%d",&a,&b),Add(a,b),Add(b,a);
53     for(int i=1;i<=n;i++) 
54         if(!col[i]) col[i]=2,dfs(i),ans+=tmp,tmp=0;
55     cout<endl;
56 }
View Code

 

 

csps模拟测试 71

T2 毛二琛

很神的DP题。q数组实际上维护的是邻项交换顺序,且满足:每个位置只会被交换一次。

那我们要把$p[i]$弄到$i$位置,如果$p[i]

也就是说:$p[i]~i-1$的交换先后顺序是确定的,$p[i]>i$的情况类似。

我们就可以直接处理出邻项的关系,顺便把无解判掉。然后直接$DP$处理出方案就行了。

 1 /*
 2     考虑排列p中的每个数怎样才能被移动到该到的地方。
 3     这显然是一些相邻的交换的顺序关系,即形如“q中i在i+1前|后”的限制。
 4     问题转化为一个大小为n-1的排列,某些地方限定了相邻两数的大小关系,求方案数。
 5     直接简单DP即可,f[i][j]表示前i个数,第i个数在前i个数中是第j小的。前缀和优化。O(n^2)
 6 */
 7 #include
 8 #include
 9 using namespace std;
10 const int mod=1e9+7;
11 int n,p[5005],dp[5005][5005],sum[5005][5005];
12 char bj[5005];
13 int main()
14 {
15     scanf("%d",&n);
16     for(register int i=1;i<=n;i++) scanf("%d",&p[i]),++p[i];
17     for(register int i=1;i<=n;i++)
18         if(p[i]for(register int j=p[i]+1;jif(bj[j]==2) return puts("0"),0;else bj[j]=1;        else for(register int j=p[i]-1;j>i;j--) if(bj[j]==1) return puts("0"),0;else bj[j]=2;
19     sum[1][1]=dp[1][1]=1;
20     for(register int i=2;i)
21         for(register int j=1;j<=i;j++)
22         {
23             if(bj[i]==1) dp[i][j]=sum[i-1][j-1];
24             else if(bj[i]==2) dp[i][j]=(sum[i-1][i-1]-sum[i-1][j-1]+mod)%mod;
25             else dp[i][j]=sum[i-1][i-1];
26             sum[i][j]=(sum[i][j-1]+dp[i][j])%mod;
27         }
28     cout<1][n-1]<<endl;
29     return 0;
30 }
View Code

 

 

 

csps模拟测试70

T3 骆驼

可能不算一个思维题,但一定是一个好题(误

构造题,打表可以发现5*5的格子里面任意点之间都能相互到达,然后我们就可以拼接了。

细节稍(ju)多,需要耐心和细心。

  1 #include
  2 using namespace std;
  3 const int nxtx[8]={-3,-2,0,2,3,2,0,-2};
  4 const int nxty[8]={0,2,-3,2,0,-2,3,-2};
  5 int tim[6][6][6][6][6][6],n,ans[1005][1005];
  6 char gt;
  7 char ok(int sx,int sy,int ex,int ey,int x,int y)
  8 {
  9     return x>=1&&x<=5&&y>=1&&y<=5&&!tim[sx][sy][ex][ey][x][y];
 10 }
 11 void search(int sx,int sy,int ex,int ey,int x,int y,int cnt)
 12 {
 13     if(tim[sx][sy][ex][ey][ex][ey]) return ;
 14     tim[sx][sy][ex][ey][x][y]=cnt;
 15     if(cnt==25) 
 16     {
 17         if(x==ex&&y==ey) gt=1;
 18         return ;
 19     }
 20     for(int i=0;i<8;i++)
 21     {
 22         if(ok(sx,sy,ex,ey,x+nxtx[i],y+nxty[i])) search(sx,sy,ex,ey,x+nxtx[i],y+nxty[i],cnt+1);
 23         if(gt) return ;
 24     }
 25     if(gt) return ;
 26     tim[sx][sy][ex][ey][x][y]=0;
 27     return ;
 28 }
 29 void out(int x,int y)
 30 {
 31     for(register int i=1;i<=x;i++,puts(""))
 32         for(register int j=1;j<=y;j++)
 33             printf("%d\n",ans[i][j]);
 34 }
 35 int main()
 36 {
 37     scanf("%d",&n);
 38     for(int i=1;i<=5;i++)
 39         for(int j=1;j<=5;j++)
 40             for(int k=1;k<=5;k++)
 41                 for(int p=1;p<=5;p++)
 42                 {
 43                     if(i==k&&j==p) continue;
 44                     gt=0;
 45                     search(i,j,k,p,i,j,1);
 46                 }
 47     for(register int i=1;i<=5;i++)
 48         for(register int j=1;j<=5;j++)
 49             if(tim[1][1][3][3][i][j]<=3) ans[i][j]=tim[1][1][3][3][i][j];
 50             else ans[i][j]=n*n-(25-tim[1][1][3][3][i][j]);
 51     if(n==5){out(5,5);return 0;}
 52     const int m=n/5;
 53     int st=3;
 54     if(!(m&1))
 55     {
 56         for(register int i=1;i<=m;i++)
 57         {
 58             if(i&1)
 59             {
 60                 for(register int j=2;j)
 61                 {
 62                     for(register int k=1;k<=5;k++)
 63                         for(register int p=1;p<=5;p++)
 64                             ans[(i-1)*5+k][(j-1)*5+p]=tim[2][1][2][3][k][p]+st;
 65                     st+=25;
 66                 }
 67                 for(register int k=1;k<=5;k++)
 68                     for(register int p=1;p<=5;p++)
 69                         ans[(i-1)*5+k][(m-1)*5+p]=tim[2][1][3][3][k][p]+st;
 70                     st+=25;
 71             }
 72             else 
 73             {
 74                 for(register int j=m;j>2;j--)
 75                 {
 76                     for(register int k=1;k<=5;k++)
 77                         for(register int p=1;p<=5;p++)
 78                             ans[(i-1)*5+k][(j-1)*5+p]=tim[1][3][1][1][k][p]+st;
 79                     st+=25;
 80                 }
 81                 for(register int k=1;k<=5;k++)
 82                     for(register int p=1;p<=5;p++)
 83                         ans[(i-1)*5+k][5+p]=tim[1][3][4][1][k][p]+st;
 84                     st+=25;
 85             }
 86         }
 87         for(register int k=1;k<=5;k++)
 88             for(register int p=1;p<=5;p++)
 89                 ans[(m-1)*5+k][p]=tim[4][3][2][5][k][p]+st;
 90         st+=25;
 91         for(register int i=m-1;i>1;i--)
 92         {
 93             for(register int k=1;k<=5;k++)
 94                 for(register int p=1;p<=5;p++)
 95                     ans[(i-1)*5+k][p]=tim[4][5][2][5][k][p]+st;
 96             st+=25;
 97         }
 98         out(n,n);
 99     }
100     else 
101     {
102         for(register int i=1;i<=m-2;i++)
103         {
104             if(i&1)
105             {
106                 for(register int j=2;j)
107                 {
108                     for(register int k=1;k<=5;k++)
109                         for(register int p=1;p<=5;p++)
110                             ans[(i-1)*5+k][(j-1)*5+p]=tim[2][1][2][3][k][p]+st;
111                     st+=25;
112                 }
113                 for(register int k=1;k<=5;k++)
114                     for(register int p=1;p<=5;p++)
115                         ans[(i-1)*5+k][(m-1)*5+p]=tim[2][1][3][3][k][p]+st;
116                     st+=25;
117             }
118             else 
119             {
120                 for(register int j=m;j>2;j--)
121                 {
122                     for(register int k=1;k<=5;k++)
123                         for(register int p=1;p<=5;p++)
124                             ans[(i-1)*5+k][(j-1)*5+p]=tim[1][3][1][1][k][p]+st;
125                     st+=25;
126                 }
127                 for(register int k=1;k<=5;k++)
128                     for(register int p=1;p<=5;p++)
129                         ans[(i-1)*5+k][5+p]=tim[1][3][4][1][k][p]+st;
130                     st+=25;
131             }
132         }
133         for(int i=m;i>2;i--)
134         {
135             if(i&1)
136             {
137                 for(register int k=1;k<=5;k++)
138                     for(register int p=1;p<=5;p++)
139                         ans[(m-2)*5+k][(i-1)*5+p]=tim[1][3][3][3][k][p]+st;
140                 st+=25;
141                 for(register int k=1;k<=5;k++)
142                     for(register int p=1;p<=5;p++)
143                         ans[(m-1)*5+k][(i-1)*5+p]=tim[1][3][1][1][k][p]+st;
144                 st+=25;
145             }
146             else 
147             {
148                 for(register int k=1;k<=5;k++)
149                     for(register int p=1;p<=5;p++)
150                         ans[(m-1)*5+k][(i-1)*5+p]=tim[1][3][3][3][k][p]+st;
151                 st+=25;
152                 for(register int k=1;k<=5;k++)
153                     for(register int p=1;p<=5;p++)
154                         ans[(m-2)*5+k][(i-1)*5+p]=tim[5][3][1][1][k][p]+st;
155                 st+=25;
156             }
157         }
158         for(register int k=1;k<=5;k++)
159             for(register int p=1;p<=5;p++)
160                 ans[(m-2)*5+k][5+p]=tim[4][4][3][3][k][p]+st;
161         st+=25;
162         for(register int k=1;k<=5;k++)
163             for(register int p=1;p<=5;p++)
164                 ans[(m-1)*5+k][5+p]=tim[1][3][3][3][k][p]+st;
165         st+=25;
166         for(register int k=1;k<=5;k++)
167             for(register int p=1;p<=5;p++)
168                 ans[(m-1)*5+k][p]=tim[3][5][2][5][k][p]+st;
169         st+=25;
170         for(register int i=m-1;i>1;i--)
171         {
172             for(register int k=1;k<=5;k++)
173                 for(register int p=1;p<=5;p++)
174                     ans[(i-1)*5+k][p]=tim[4][5][2][5][k][p]+st;
175             st+=25;
176         }
177         out(n,n);
178     }
179     return 0;
180 }
View Code

 

csps模拟测试 68

T3 f

首先有一个很显然的性质:$a$ $xor$ $x$与 $b$ $xor$ $x$的大小关系,只与$ a $,$ b $不同的最高位有关。

考虑预处理出来直接枚举,复杂度$O(2^k)$,可以有$ 55pts $

值得一提的是$ 75pts $的部分分做法,由于$ p<=1e4 $,所以只需要维护有用的信息,复杂度$O(pk)$

正解是二分,求$ p $大数直接二分,关键是$ check $,很巧妙地$meet$ $in$ $middle$

由于前$ k/2 $和后$ k/2 $互不影响,可以拆开算,用个单调指针扫一下就好了。

第二问我是直接暴力,先把逆序对个数$

复杂度$O(2^{k/2}logn)$

 1 #include
 2 #include
 3 #include
 4 #include
 5 #define mp make_pair
 6 #define int long long
 7 #define N 500005
 8 using namespace std;
 9 int a[N],t[31][2];
10 int n,k,p,lmt;
11 pair<int,int> kx[2][N];
12 int tot[2],sum[N],kl[N],lk[N];
13 map<int,int>ct;
14 struct Trie{
15     int ch[N<<5][2],tot,cnt[N<<5];
16     inline void insert(int x)
17     {
18         int p=1;
19         for(register int i=k-1;~i;i--)
20         {
21             int dex=(x>>i)&1;
22             if(dex) t[i][1]+=cnt[ch[p][dex^1]];
23             else t[i][0]+=cnt[ch[p][dex^1]];
24             if(!ch[p][dex]) ch[p][dex]=++tot;
25             p=ch[p][dex];
26             cnt[p]++;
27         }
28     }
29 }T;
30 inline int read()
31 {
32     int x=0;char c=getchar();
33     while(c>'9'||c<'0') c=getchar();
34     while(c<='9'&&c>='0') x=x*10+c-48,c=getchar();
35     return x;
36 }
37 void Qsearch(int pos,int now,int val,int opt)
38 {
39     if(pos==lmt) {kx[opt][now]=mp(val,now);return ;}
40     Qsearch(pos-1,now<<1,val+t[pos][0],opt);
41     Qsearch(pos-1,now<<1|1,val+t[pos][1],opt);
42 }
43 int check(int x)
44 {
45     int ans=0,tl=-1;
46     for(register int i=(1<0])-1;~i;--i)
47     {
48         while(kx[1][tl+1].first+kx[0][i].first<=x&&tl+1<1<1]) tl++;
49         ans+=tl+1;
50     }
51     return ans;
52 }
53 signed main()
54 {
55     T.tot=1;
56     n=read(),k=read(),p=read();
57     for(register int i=1;i<=n;i++) a[i]=read(),T.insert(a[i]);
58     lmt=-1;Qsearch(k/2-1,0,0,0);tot[0]=k/2;
59     lmt=k/2-1;Qsearch(k-1,0,0,1);tot[1]=k-k/2;
60     sort(kx[0],kx[0]+(1<0]));
61     sort(kx[1],kx[1]+(1<1]));
62     int l=0,r=n*n/2,ans=0;
63     while(l<=r)
64     {
65         int mid=l+r>>1;
66         if(check(mid)1;
67         else ans=mid,r=mid-1;
68     }
69     printf("%lld ",ans);
70     
71     int tmp=0,tl=-1;
72     for(register int i=(1<0])-1;~i;--i)
73     {
74         while(kx[1][tl+1].first+kx[0][i].first1<1<1]) tl++;
75         tmp+=tl+1;
76     }
77     for(register int i=0;i<1<1];i++) kl[kx[1][i].second]=kx[1][i].first;
78     for(register int i=0;i<1<0];i++) lk[kx[0][i].second]=kx[0][i].first;
79     p-=tmp;
80     for(register int i=0;i<1<0];i++)
81         ct[kx[0][i].first]++;
82     tmp=0;
83     for(register int i=0;i<1<1];i++)
84     {
85         int nxt=tmp+ct[ans-kl[i]];
86         if(nxt>=p)
87         {
88             int ak=0;
89             for(register int j=0;j<1<0];j++)
90             {
91                 if(lk[j]==ans-kl[i]) ak++;
92                 if(ak+tmp==p) {printf("%lld\n",i<0]|j);return 0;}
93             }
94         }
95         tmp=nxt;
96     }
97     return 0;
98 }
View Code

 

csps模拟测试 69

T2 array

单调栈好题,由于区间的$MAXN$一定是递减的,显然若$i

所以维护一个单调递减栈来维护$MAXN$,那要弹出某个元素的时候,能找到它对应的左端点。

这个可以再开一个数组维护,$mn[i]$表示$s[i-1]$到$s[i]$的最优左端点,可以直接维护。

 1 #include
 2 #include
 3 using namespace std;
 4 const int N=1e7+7;
 5 int mx,mn,a[N],ans,s[N],top,k[N];
 6 inline int read()
 7 {
 8     int x=0;char c=getchar();
 9     while(c<'0'||c>'9') c=getchar();
10     while(c>='0'&&c<='9') x=x*10+c-48,c=getchar();
11     return x;
12 }
13 int main()
14 {
15     int n=read();
16     for(register int i=1;i<=n;++i) a[i]=read();
17     for(register int i=1;i<=n;++i)
18     {
19         int now=i;
20         while(top&&a[s[top]]<=a[i])
21         {
22             ans=max(ans,s[top]-k[top]+1);
23             if(a[k[top]]<=a[now]) now=k[top];
24             top--;
25         }
26         s[++top]=i,k[top]=now;
27     }
28     while(top) ans=max(ans,s[top]-k[top]+1),top--;
29     printf("%d\n",ans);
30     return 0;
31 }
View Code

 

csps模拟测试 59

T2 Silhouette

神题

首先有一个很显然的性质:答案与$a$,$b$的顺序无关,这个很好证。

每个点有一个最大值,即点$(i,j)$为$min(a_i,b_j)$ 

手模一下样例可以发现,整张网格的最大值分成若干块,而块的数目不会超过$2*n$。

考虑在这些块上入手,容易发现块与块之间是互不影响的。

枚举每一块,又可以发现一个十分优秀的性质:这些块要么是矩形,要么是L形。

提取子问题:

给定一个$a*b$的矩形,矩形内每个数为$[0,s]$,要求每一行每一列的最大值为s求方案数。

容斥,设$f[i]$表示至少i行不满足条件的方案数。

先选出$i$行,是一个$C_a^i$,

然后枚举每一列的情况,这一列中枚举的那i个位置是一定要不合法的,也就是只能在$[0,s-1]$中选,即$s^i$。

要保证这一列合法,另外$a-i$个位置一定要有一个$s$,$(s+1)^{(a-i)}-s^{(a-i)}$。

每一列都是这样,最后再直接^b即可

部分题解乱写_第2张图片

再考虑L形的情况,首先L形的只有可能是两个矩形的交汇处不合法(想一想为什么),我们在枚举的时候不合法的点只能在那个矩形里面选取

所以我们只需要把上式略微改一下就行了。

容斥一下就好了

 1 #include
 2 #include
 3 #include
 4 #define int long long
 5 using namespace std;
 6 const int mod=1e9+7,N=1e5+5;
 7 int a[N],b[N],n,js[N],js_inv[N],ans=1,tt[N<<1],tot;
 8 inline int read()
 9 {
10     int x=0;char c=getchar();
11     while(c<'0'||c>'9')   c=getchar();
12     while(c>='0'&&c<='9') x=x*10+c-48,c=getchar();
13     return x;
14 }
15 inline int C(int n,int m){return js[n]*js_inv[m]%mod*js_inv[n-m]%mod;}
16 inline int pow(int a,int b)
17 {
18     int ans=1;
19     for(;b;b>>=1,a=a*a%mod) if(b&1) ans=ans*a%mod;
20     return ans;
21 }
22 inline int calc(const int a,const int b,const int c,const int d,const int s)
23 {
24     int cnt=0;
25     for(register int i=0;i<=a;i++)
26     {
27         int sum=C(a,i)*pow(pow(s,i)%mod*((pow(s+1,a+c-i)-pow(s,a+c-i))%mod+mod)%mod,b)%mod*pow(pow(s,i)*pow(s+1,a-i)%mod,d)%mod;
28         if(i&1) (cnt-=sum)%=mod;
29         else (cnt+=sum)%=mod;
30     }
31     return (cnt%mod+mod)%mod;
32 }
33 inline void work()
34 {
35     register int i=n,j=n,lst1=n+1,lst2=n+1;
36     for(int k=tot;k;k--)
37     {
38         while(i&&a[i-1]==tt[k]) i--;
39         while(j&&b[j-1]==tt[k]) j--;
40         (ans*=calc(lst1-i,lst2-j,n-lst1+1,n-lst2+1,tt[k]))%=mod;
41         lst1=i,lst2=j;
42     }
43 }
44 signed main()
45 {
46     js[0]=1;
47     for(register int i=1;i<=N-5;i++) js[i]=js[i-1]*i%mod;
48     js_inv[N-5]=pow(js[N-5],mod-2);
49     for(register int i=N-6;i>=1;i--) js_inv[i]=js_inv[i+1]*(i+1)%mod;
50     js_inv[0]=1;
51     n=read();
52     for(register int i=1;i<=n;i++) a[i]=read(),tt[++tot]=a[i];
53     for(register int i=1;i<=n;i++) b[i]=read(),tt[++tot]=b[i];
54     sort(tt+1,tt+tot+1);tot=unique(tt+1,tt+tot+1)-tt-1;
55     sort(a+1,a+n+1);sort(b+1,b+n+1);
56     if(a[n]^b[n]) return puts("0"),0;
57     work();
58     printf("%lld\n",ans);
59     return 0;
60 }
View Code

 

模拟测试 64

T2 sum

一道很好的题,表面上是一道数学题。

但我们易得:

$S_n^m=S_{n-1}^m*2-C_{n-1}^m$

$S_n^m=S_n^{m-1}+C_n^m$

当时我只想到可以过$n,m$相同的测试点,但实际上合起来莫队就行了。

注意:思路的灵活转化,知识点的运用。

复杂度$O(n\sqrt{n})$

 1 #include
 2 #include
 3 #include
 4 using namespace std;
 5 const int mod=1e9+7,N=1e5+5,inv2=5e8+4;
 6 void moded(int &x){if(x>=mod)x-=mod;if(x<0) x+=mod;return ;}
 7 int q,js[N],js_inv[N],bl[N],ak[N];
 8 int C(int n,int m){if(m>n) return 0;return 1ll*js[n]*js_inv[m]%mod*js_inv[n-m]%mod;}
 9 inline int qpow(int a,int b)
10 {
11     int ans=1;
12     for(;b;b>>=1,a=1ll*a*a%mod) if(b&1) ans=1ll*ans*a%mod;
13     return ans;
14 }
15 void pre()
16 {
17     js[0]=1;
18     for(register int i=1;i<=100000;i++) js[i]=1ll*js[i-1]*i%mod;
19     js_inv[100000]=qpow(js[100000],mod-2);js_inv[0]=1;
20     for(register int i=99999;i;i--) js_inv[i]=1ll*js_inv[i+1]*(i+1)%mod;
21     return ;
22 }
23 struct query{
24     int l,r,id;
25     inline void init(int i){scanf("%d%d",&r,&l);id=i;}
26     friend bool operator <(const query a,const query b)
27     {
28         return bl[a.l]==bl[b.l]?a.rb.l;
29     }
30 }Q[N];
31 int main()
32 {
33     pre();
34     int id,q;scanf("%d%d",&id,&q);
35     for(register int i=1;i<=100000;i++) bl[i]=(i-1)/333+1;
36     for(register int i=1;i<=q;i++) Q[i].init(i);
37     int l=0,r=1,ans=1;
38     sort(Q+1,Q+q+1);
39     for(register int i=1;i<=q;i++)
40     {
41         while(lC(r,l));
42         while(l>Q[i].l) moded(ans-=C(r,l)),l--;
43         while(r2-C(r,l)),r++;
44         while(r>Q[i].r) r--,ans=1ll*(ans+C(r,l))*inv2%mod;
45         ak[Q[i].id]=ans;
46     }
47     for(register int i=1;i<=q;i++) printf("%d\n",ak[i]);
48     return 0;
49 }
View Code

 

模拟测试 64

T1 trade

可反悔贪心,假设当前有一个$a$和$b$$(a

假设存在一点$c$,$(a,c)$方案比$(a,b)$优,那么我们的收益是$c-a$,而$b-a+c-b=c-a$,我们就成功反悔了。

注:反悔的时候要放两个当前值,一个用来选,一个来反悔。

 1 #include
 2 #include
 3 #include
 4 #define int long long
 5 using namespace std;
 6 priority_queue<int>Q;
 7 int a[100005];
 8 signed main()
 9 {
10     int n,ans=0;scanf("%lld",&n);
11     for(register int i=1;i<=n;i++) scanf("%lld",&a[i]);
12     for(register int i=1;i<=n;i++)
13     {
14         if(!Q.size()) {Q.push(-a[i]);continue;}
15         int x=-Q.top();
16         if(a[i]>x)
17         {
18             ans+=a[i]-x;
19             Q.pop();Q.push(-a[i]);
20         }
21         Q.push(-a[i]);
22     }
23     cout<endl;
24     return 0;
25 }
View Code

 

模拟测试 62

T2 Permutation

将序列问题改成图论问题。

还有就是结论。

 

模拟测试67

T1 神炎皇

是道好题了。

很容易得式子 $ \sum \limits_{a=1}^{n}\sum \limits_{b=1}^{n-a} [(i+b)\mid(a*b)] $

枚举质因子得$ \sum \limits_{d=1}^{n}\sum \limits_{a=1}^{\left \lfloor \frac{n}{d} \right \rfloor}\sum \limits_{b=1}^{\left \lfloor \frac{n}{d}\right\rfloor}[(a+b)\mid(a*b*d)]*[gcd(a,b)==1] $

直接枚举不好优化。易发现$ a+b\leqslant\sqrt{n} $

我们可以先枚举$a+b=k$,然后可以发现$d$有$ \frac{n}{k^2} $个

(由于$ a $,$ b $互质,所以$ a $,$ b $均与$ a+b $互质,所以$ k \mid d $,假设$d=c*k$,则$ c*k^2<=n $,即$c$有$ \frac{n}{k^2}$个)

然后$a+b=k$且$gcd(a,b)==1$的方案数是$\varphi(k)$。

我想证明一下(我太菜了)

$a\perp b$那么$a\perp (a+b)$ 用更相减损法,若$gcd(a,a+b)!=1$,那么$gcd(a,b)!=1$

即满足$gcd(a,k)==1$的$a$有$\varphi(k)$个,然后就行了。

时间复杂度$O(\sqrt{n})$

 1 #include
 2 #include
 3 #include
 4 using namespace std;
 5 const int N=1e7+7;
 6 long long n,ans;
 7 char v[N];
 8 int p[N],phi[N],tot;
 9 int main()
10 {
11     cin>>n;
12     long long k=sqrt(n);
13     phi[1]=1;
14     for(register int i=2;i<=k;i++)
15     {
16         if(!v[i]) p[++tot]=i,phi[i]=i-1;
17         for(register int j=1;j<=tot&&p[j]*i<=k;j++)
18         {
19             v[i*p[j]]=1;
20             if(i%p[j]==0) {phi[i*p[j]]=phi[i]*p[j];break;}
21             phi[i*p[j]]=phi[i]*(p[j]-1);
22         }
23     }
24     for(register int i=2;i<=k;i++)
25         ans+=(n/i/i)*phi[i];
26     cout<endl;
27     return 0;
28 }
View Code

 顺便说一下,我考试的时候打出了人生第一个线筛(误) 筛的是$\prod 2c_i+1$(那个$low$数组可以去掉)

 1 #include
 2 #include
 3 const int N=10;
 4 using namespace std;
 5 int f[N+5],low[N+5],prime[N],tot,ans;
 6 char v[N+5],cm[N+5];
 7 int main()
 8 {
 9     f[1]=1;
10     for(register int i=2;i<=N;i++)
11     {
12         if(!v[i]) prime[++tot]=i,low[i]=i,f[i]=3,cm[i]=1;
13         for(register int j=1;j<=tot&&prime[j]*i<=N;j++)
14         {
15             v[i*prime[j]]=1;
16             if(i%prime[j]==0)
17             {
18                 f[i*prime[j]]=f[i/low[i]]*(2*cm[i]+3);
19                 low[i*prime[j]]=low[i]*prime[j];
20                 cm[i*prime[j]]=cm[i]+1;
21                 break;
22             }
23             f[i*prime[j]]=f[i]*3;
24             low[i*prime[j]]=prime[j];
25             cm[i*prime[j]]=1;
26         }
27     }
28     for(register int i=2;i<=N;i++) cerr<' '<f[i];
29     ans-=N;
30     cout<endl;
31     return 0;
32 }
View Code

你可能感兴趣的:(部分题解乱写)