先总结一下
第二次
T1 搜索+剪枝
1 #include<cstdio>
2 #include<iostream>
3 #define ll long long
4 using namespace std;
5 const int maxn=8005;
6 int a[maxn],n,js[maxn];
7 bool jk[maxn];
8 ll ans;
9 bool judge(int l,int r)
10 {
11 int i=l;
12 while(i<r)
13 {
14 if(a[i]+1!=a[i+1])return 0;
15 else i++;
16 }
17 return 1;
18 }
19 void out()
20 {
21 for(int i=1;i<=(1<<n);i++)
22 {
23 cout<<a[i]<<" ";
24 }
25 cout<<endl;
26 }
27 void search(int num,int last)
28 {
29 //out();//cout<<"->"<<endl;
30 if(judge(1,1<<n)){ans+=js[num];return ;}
31 if(last==n+1)return ;
32 int must1=0,must2=0;
33 for(int j=1;j<=(1<<n);j+=(1<<last))
34 {
35 if(!judge(j,j+(1<<last)-1)&&!must1)must1=j;
36 else if(!judge(j,j+(1<<last)-1)&&must1&&!must2)must2=j;
37 else if(!judge(j,j+(1<<last)-1))return ;
38 }
39 if(!must1&&!must2)search(num,last+1);
40 else if(!must2)
41 {
42 int j=must1,k=must1+(1<<(last-1));
43 int kx=0;
44 while(kx<(1<<(last-1)))
45 {
46 swap(a[j+kx],a[k+kx]);
47 kx++;
48 }
49 search(num+1,last+1);
50 kx=0;
51 while(kx<(1<<(last-1)))
52 {
53 swap(a[j+kx],a[k+kx]);
54 kx++;
55 }
56 return ;
57 }
58 else
59 {
60 int jj[2]={},kk[2]={};
61 // cout<<must1<<" "<<must2<<endl;
62 jj[0]=must1,jj[1]=must1+(1<<(last-1));
63 kk[0]=must2,kk[1]=must2+(1<<(last-1));
64 //cout<<jj[1]<<" "<<kk[1]<<endl;
65 for(int i=0;i<=1;i++)
66 for(int j=0;j<=1;j++)
67 {
68 //out();
69 //cout<<jj[i]<<" "<<kk[j]<<endl;
70 int kx=0;
71 while(kx<(1<<(last-1)))
72 {
73 swap(a[jj[i]+kx],a[kk[j]+kx]);
74 kx++;
75 }
76 search(num+1,last+1);
77 kx=0;
78 while(kx<(1<<(last-1)))
79 {
80 swap(a[jj[i]+kx],a[kk[j]+kx]);
81 kx++;
82 }
83
84 }
85 }
86 return ;
87 }
88 int main()
89 {
90 scanf("%d",&n);
91 js[1]=1;
92 for(int i=2;i<=n;i++)
93 js[i]=js[i-1]*i;
94 for(int i=1;i<=(1<<n);i++)
95 {
96 scanf("%d",&a[i]);
97 }
98 search(0,1);
99 cout<<ans<<endl;
100 return 0;
101 }
T2 划艇 高难标记
31分算法:线段树优化DP
AC算法:
区间离散化。
跨区间显然,同区间组合计数。
1 #include<cstdio>
2 #include<iostream>
3 #include<algorithm>
4 #define mod DeepinC
5 #define maxn 505
6 using namespace std;
7 int l[maxn*2],len[maxn*2],sum[maxn*2][maxn*2],num[maxn*2][maxn*2],a[maxn],b[maxn],f[maxn][maxn*2],inv[maxn*10+5];
8 const int mod=1e9+7;
9 int qpower(int a,int b)
10 {
11 int ans=1;
12 while(b)
13 {
14 if(b&1)ans=1ll*ans*a%mod;
15 b>>=1;
16 a=1ll*a*a%mod;
17 }
18 return ans;
19 }
20 void get_inv()
21 {
22 for(int i=1;i<=500;i++)
23 inv[i]=qpower(i,mod-2);
24 return ;
25 }
26 int main()
27 {
28 get_inv();
29 int n,tot=0,ans=0;
30 scanf("%d",&n);
31 for(int i=1;i<=n;i++)
32 {
33 scanf("%d%d",&a[i],&b[i]);
34 b[i]++;
35 l[++tot]=a[i];
36 l[++tot]=b[i];
37 }
38 sort(l+1,l+tot+1);
39 tot=unique(l+1,l+tot+1)-l-1;
40 for(int i=1;i<tot;i++)
41 {
42 len[i]=l[i+1]-l[i];
43 //cout<<i<<" "<<len[i]<<endl;
44 }
45 for(int i=1;i<=n;i++)
46 {
47 a[i]=lower_bound(l+1,l+tot+1,a[i])-l;
48 b[i]=lower_bound(l+1,l+tot+1,b[i])-l-1;
49 }
50 sum[0][0]=1;
51 for(int i=1;i<=n;i++)
52 {
53 sum[i][0]=1;
54 }
55 for(int j=1;j<=tot;j++)sum[0][j]=1;
56 for(int i=1;i<=n;i++)
57 {
58 for(int j=a[i];j<=b[i];j++)
59 {
60 f[i][j]=1ll*sum[i-1][j-1]*len[j]%mod;
61 // cout<<f[i][j]<<endl;
62 int o=1,C=(len[j]-1)%mod;
63 for(int k=i-1;k;k--)
64 {
65 if(a[k]>j||b[k]<j)continue;
66 o++;
67 C=1ll*C*(o+len[j]-2)%mod*inv[o]%mod;
68 //cout<<C<<endl;
69 f[i][j]=(f[i][j]+1ll*C*sum[k-1][j-1]%mod)%mod;
70 }
71 ///cout<<f[i][j]<<endl;
72 ans+=f[i][j];
73 ans%=mod;
74 }
75 for(int j=1;j<=tot;j++)
76 sum[i][j]=((1ll*sum[i-1][j]+sum[i][j-1])%mod-sum[i-1][j-1]+f[i][j]+mod)%mod;
77 }
78 cout<<ans<<endl;
79 return 0;
80 }
T3 放棋子:DP
设g[i][j][k]表示用k个棋子填满i行j列的方案,设f[i][j][k]表示用前k种棋子填满i行j列的方案
容斥计算g数组:
那么f数组 :
最终答案:
(图片来自https://www.cnblogs.com/yanshannan/p/9467292.html,特此鸣谢)
AC代码:
1 #include<cstdio>
2 #include<iostream>
3 #include<cstring>
4 #define maxn 35
5 using namespace std;
6 const int mod=1e9+9;
7 int C[maxn*maxn][maxn*maxn],g[maxn][maxn],f[maxn][maxn][maxn*maxn],cn[maxn];
8 int moded(int x)
9 {
10 if(x<0)return x+mod;
11 return x>=mod?x-mod:x;
12 }
13 int main()
14 {
15 // freopen("out.txt","w",stdout);
16 int n,m,c,tot=0;
17 scanf("%d%d%d",&n,&m,&c);
18 for(int i=1;i<=c;i++)
19 {
20 scanf("%d",&cn[i]);
21 tot=max(tot,cn[i]);
22 }
23 for(int i=1;i<=900;i++)
24 {
25 C[i][0]=C[i][i]=1;
26 for(int j=1;j<i;j++)
27 C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
28 }
29 f[0][0][0]=1;
30 int ans=0;
31 for(int k=1;k<=c;k++)
32 {
33 memset(g,0,sizeof(g));
34 for(int i=1;i<=n;i++)
35 for(int j=1;j<=m;j++)
36 {
37 g[i][j]=C[i*j][cn[k]];
38 for(int ii=0;ii<=i;ii++)
39 for(int jj=0;jj<=j;jj++)
40 {
41 if(ii==i&&jj==j)continue;
42 g[i][j]=(g[i][j]-1ll*g[ii][jj]*C[i][ii]%mod*C[j][jj]%mod+mod)%mod;
43 }
44 //cout<<k<<" "<<i<<" "<<j<<" "<<" "<<g[i][j]<<endl;
45 }
46 for(int i=1;i<=n;i++)
47 for(int j=1;j<=m;j++)
48 {
49 for(int ii=0;ii<i;ii++)
50 for(int jj=0;jj<j;jj++)
51 {
52 f[i][j][k]=(f[i][j][k]+1ll*f[ii][jj][k-1]*C[n-ii][i-ii]%mod*C[m-jj][j-jj]%mod*g[i-ii][j-jj]%mod)%mod;
53 //if(k==c&&i==n&&j==m)cout<<ii<<" "<<jj<<" "<<f[ii][jj][k-1]<<endl;
54 }
55 if(k==c)
56 {
57 ans=moded(ans+f[i][j][c]);
58 //if(i==n)cout<<i<<" "<<j<<" "<<f[i][j][c]<<endl;
59 }
60 }
61
62 }
63 cout<<ans<<endl;
64 return 0;
65 }
第三次
爆零。。。
T1:序列
乱搞,(鬼知道我打了一个什么倍增)
AC代码:(不会告诉你我是QJ的)
感谢wd大佬的帮助%%DeepinC
1 #include<cstdio>
2 #include<iostream>
3 #include<cmath>
4 #include<cstring>
5 #define maxn 200005
6 #define maxq 1001
7 #include<vector>
8 #include<algorithm>
9 #define LL long long
10 #define ts puts("--------");
11 using namespace std;
12 LL n,a[maxn],ans,need1[maxn],A[maxn],maxx,b[maxn][21],num[maxn],fr[maxn][21],Num[105],nuM[105],toty;
13 LL prime[maxq*10000+5],tot,frprime[maxq*10000+5];
14 bool isnotprime[maxq*10000+5];
15 LL gcd(LL a,LL b)
16 {
17 return b==0?a:gcd(b,a%b);
18 }
19 LL qpower(LL a,LL b)
20 {
21 LL ans=1;
22 while(b)
23 {
24 if(b&1)ans=ans*a;
25 a=a*a;
26 b>>=1;
27 }
28 return ans;
29 }
30 void pre()
31 {
32 for(int i=2;i<=maxq*10000;i++)
33 {
34 if(!isnotprime[i])
35 {
36 prime[++toty]=i;
37 frprime[i]=i;
38 }
39 for(int j=1;j<=toty;j++)
40 {
41 if(i*prime[j]>maxq*10000)break;
42 isnotprime[i*prime[j]]=1;
43 frprime[i*prime[j]]=prime[j];
44 if(!i%prime[j])break;
45 }
46 }
47 }
48 LL GetUse(LL x)
49 {
50 LL mt=x;
51 if(x%10==0){
52 while(x%10==0)x/=10;
53 return x==1?10ll:mt;
54 }
55 if(x%7==0){
56 while(x%7==0)x/=7;
57 return x==1?7ll:mt;
58 }
59 if(x%6==0){
60 while(x%6==0)x/=6;
61 return x==1?6ll:mt;
62 }
63 if(x%5==0){
64 while(x%5==0)x/=5;
65 return x==1?5ll:mt;
66 }
67 if(x%3==0){
68 while(x%3==0)x/=3;
69 return x==1?3:mt;
70 }
71 if(x%2==0){
72 while(x%2==0)x/=2;
73 return x==1?2:mt;
74 }
75 return mt;
76 }
77 bool query(LL st,LL len)
78 {
79 LL cnt=0;
80 for(LL i=st;i<=st+len-1;i++)
81 {
82 num[++cnt]=a[i];
83 }
84 sort(num+1,num+cnt+1);
85 for(LL i=2;i<=cnt;i++)if(num[i]==num[i-1]){return 0;}
86 return 1;
87 }
88 LL Get(LL x,LL q)
89 {
90 if(q==1)return x;
91 while(x%q==0)x/=q;
92 return x;
93 }
94 bool judge(LL len)
95 {
96 LL Q=0,now,F;
97 for(LL i=1;i<=n-len+1;i++)
98 {
99 now=0;Q=0;
100 for(LL t=17;t>=1;t--)
101 {
102 if((1<<t)+now<=len){
103 if(b[i+now][t]==-1){break;}
104 // cout<<i<<' '<<len<<' '<<t<<' '<<now<<" from "<<n-len+1<<endl;
105 if(!Q){Q=b[i+now][t];F=fr[i+now][t];}
106 else if(b[i+now][t]==-1||Q!=b[i+now][t]||fr[i+now][t]!=F){break;}
107 now+=(1<<t);
108 if(now==len){
109 if(Q==1||query(i,len))return 1;
110 else break;
111 }
112 if(now==len-1){
113 if(Q==1&&a[i+len-1]==a[i+len-2])return 1;
114 if(a[i+len-1]>a[i+len-2]&&query(i,len)&&a[i+len-1]%a[i+len-2]==0)
115 {
116 LL t=a[i+len-1]/a[i+len-2];
117 if(GetUse(t)==Q)return 1;
118 }
119 else
120 if(a[i+len-1]<a[i+len-2]&&query(i,len)&&a[i+len-2]%a[i+len-1]==0)
121 {
122 LL t=a[i+len-2]/a[i+len-1];
123 if(GetUse(t)==Q)return 1;
124 }
125 break;
126 }
127 }
128 }
129 }
130 return 0;
131 }
132 int main()
133 {
134 scanf("%lld",&n);
135 for(LL i=1;i<=n;i++)scanf("%lld",&a[i]);
136 for(LL i=2;i<=n;i++)
137 if(a[i]%a[i-1]==0){
138 b[i-1][1]=a[i]/a[i-1];
139 b[i-1][1]=GetUse(b[i-1][1]);
140 fr[i-1][1]=Get(a[i-1],b[i-1][1]);
141 }
142 else if(a[i-1]%a[i]==0){
143 b[i-1][1]=a[i-1]/a[i];
144 b[i-1][1]=GetUse(b[i-1][1]);
145 fr[i-1][1]=Get(a[i],b[i-1][1]);
146 }
147 else b[i-1][1]=-1;
148 b[n][1]=-1;
149 for(LL i=2;i<=17;i++)
150 for(LL j=1;j<=n;j++){
151 if(b[j][i-1]==b[j+(1<<(i-1))][i-1]&&b[j][i-1]!=-1&&fr[j][i-1]==fr[j+(1<<(i-1))][i-1])
152 b[j][i]=b[j][i-1],fr[j][i]=fr[j][i-1];
153 else b[j][i]=-1;
154 }
155 LL l=2,r=n;
156 while(l<=r)
157 {
158 int mid=l+r>>1;
159 if(judge(mid)){ans=mid;l=mid+1;}
160 else r=mid-1;
161 }
162 cout<<ans<<endl;
163 return 0;
164 }
T2:熟练剖分
概率期望不是DP
值得一提的是,wq学长为我们证明了某种树DP复杂度(枚举深度,子树大小。。):设(x,y)表示树上的一对节点对,那么考虑每个节点的贡献,每个节点会被它的父链上的每个节点计算一次,所以每个节点被计算n次即总复杂度n×n。
还有很重要的是,打成相加形式才是n^2,不然是n^3
n^2
1 for(int j=size[x];j>=0;j--) 2 { 3 for(int k=0;k<=min(j,size[y]);k++) 4 { 5 f[x][j][1]=min(f[x][j][1],f[x][j-k][1]+f[y][k][1]); 6 f[x][j][0]=min(f[x][j][0],f[x][j-k][0]+min(f[y][k][0],f[y][k][1])); 7 } 8 }
n^3
1 for(int j=size[x];j>=0;j--) 2 { 3 for(int k=size[y];k>=0;k--) 4 { 5 f[x][j+k][1]=min(f[x][j+k][1],f[x][j][1]+f[y][k][1]); 6 f[x][j+k][0]=min(f[x][j+k][0],f[x][j][0]+min(f[y][k][0],f[y][k][1])); 7 } 8 }
这道题就是这一类
AC代码:
1 #include<iostream>
2 #include<cstdio>
3 #include<vector>
4 #include<cstring>
5 using namespace std;
6 const int mod=1e9+7;
7 int n,indu[3100],root;
8 vector<int>son[3100];
9 long long f[3100][3100],g[2][2][3100],dep[3100];
10 long long pow(long long a,long long b){
11 long long ans=1;
12 a%=mod;
13 while(b){
14 if(b&1) ans=(ans*a)%mod;
15 b>>=1;
16 a=(a*a)%mod;
17 }
18 return ans%mod;
19 }
20 long long max(long long a,long long b){
21 return a>b?a:b;
22 }
23 void dfs(int x){
24 if(son[x].size()==0){
25 f[x][0]=1;
26 //printf("x=%d 代价=%d 方案数=%d\n",x,0,f[x][0]);
27 return;
28 }
29 for(int i=0;i<son[x].size();i++){
30 dfs(son[x][i]);
31 dep[x]=max(dep[x],dep[son[x][i]]+1);
32 }
33 memset(g,0,sizeof(g));
34 for(int i=1;i<=dep[son[x][0]]+1;i++){
35 g[0][0][i]=f[son[x][0]][i-1];
36 g[0][1][i]=f[son[x][0]][i];
37 //printf("g[%d][%d][%d]=%d g[%d][%d][%d]=%d\n",0,0,i,g[0][0][i],0,1,i,g[0][1][i]);
38 }
39 g[0][1][0]=f[son[x][0]][0];
40 int cur=0,upw=dep[son[x][0]]+1;
41 for(int i=1;i<son[x].size();i++){
42 memset(g[cur^1],0,sizeof(g[cur^1]));
43 for(int j=0;j<=upw;j++){
44 for(int k=0;k<=dep[son[x][i]];k++){
45 (g[cur^1][0][max(j,k+1)]+=g[cur][0][j]*f[son[x][i]][k]%mod)%=mod;
46 (g[cur^1][1][max(j,k+1)]+=g[cur][1][j]*f[son[x][i]][k]%mod)%=mod;
47 (g[cur^1][1][max(j,k)]+=g[cur][0][j]*f[son[x][i]][k]%mod)%=mod;
48 }
49 }
50 upw=max(dep[son[x][i]]+1,upw);
51 cur^=1;
52 }
53 memcpy(f[x],g[cur][1],sizeof(f[x]));
54 //for(int i=0;i<=dep[x];i++) printf("x=%d 代价=%d 方案=%d\n",x,i,f[x][i]);
55
56 }
57 int main(){
58 scanf("%d",&n);
59 int x,y;
60 long long num=1;
61 for(int i=1;i<=n;i++){
62 scanf("%d",&x);
63 for(int j=1;j<=x;j++){
64 scanf("%d",&y);
65 son[i].push_back(y);
66 indu[y]++;
67 }
68 if(x) (num*=pow(x,mod-2)%mod)%=mod;
69 }
70 for(int i=1;i<=n;i++){
71 if(indu[i]==0){
72 root=i;
73 break;
74 }
75 }
76 dfs(root);
77 long long sum=0;
78 for(int i=1;i<=n;i++) sum=(sum+i*f[root][i]%mod)%mod;
79 //cout<<sum<<" "<<num<<endl;
80 printf("%lld\n",(sum%mod*num%mod)%mod);
81 }
T3:建造游乐场 高难标记
毒瘤题,码量极短,思维量极高23333333
为了保证考试总结的完整性 我决定借用外力(粘贴题解)
先不粘AC代码了(心虚)
第四次
T1 礼物:
实际上是个及其简单的概率期望
But....我经过一下午的钻研(死皮赖脸缠着学长)(以致学长无法吃鸡)才大致明白了
f[i]=∑f[s]*p[j]+∑p[j]*f[i]+1 因为设f[i]表示买到状态为i到最终状态的期望次数 那么那么f[i]是可以由他的下一个状态转移过来 即所有的f[s].如果按原有的逻辑顺序对于f[i]来说转移到f[s]的概率是显然的 但是因为是倒着推,很显然f[s]就应该累加到f[i]上
所以:
正向求概率,反向求期望!
1 #include<cstdio>
2 #include<iostream>
3 #define MAXN 25
4 using namespace std;
5 double p[MAXN],f[1<<22],wp[MAXN];
6 int w[MAXN];
7 int main()
8 {
9 int n;long long ans1=0;
10 scanf("%d",&n);
11 int maxk=(1<<n)-1;
12 for(int i=1;i<=n;i++)
13 {
14 scanf("%lf%d",&p[i],&w[i]);
15 ans1+=w[i];
16 }
17 cout<<ans1<<endl;
18 f[maxk]=0;
19 for(int i=0;i<=maxk;i++)
20 {
21 int state=i;
22 for(int j=1;j<=n;j++)
23 {
24 if((state&(1<<(j-1))))continue;
25 wp[state]+=p[j];
26 }
27 }
28 for(int i=maxk-1;i>=0;i--)
29 {
30 f[i]=1;
31 for(int j=1;j<=n;j++)
32 {
33 if((i&(1<<(j-1))))continue;
34 f[i]+=(f[i|(1<<(j-1))]*p[j]);
35 }
36 f[i]/=wp[i];
37 //cout<<i<<' '<<f[i]<<endl;
38 }
39 printf("%.3lf",f[0]);
40 return 0;
41 }
T2:通讯
Tarjan缩点+贪心板子题
1 #include<cstdio>
2 #include<iostream>
3 #include<queue>
4 #include<cstring>
5 #define LL long long
6 #define mem(a) memset(a,0,sizeof(a))
7 #define MAXN 200005
8 #define LL long long
9 using namespace std;
10 struct node{
11 LL to[MAXN],head[MAXN],w[MAXN],nxt[MAXN],d[MAXN],low[MAXN],dfn[MAXN],s[MAXN],top,tot,num,out[MAXN],n,m,c[MAXN];
12 LL To[MAXN],Head[MAXN],W[MAXN],Nxt[MAXN],cnt,Cnt,ans;
13 bool in_s[MAXN];
14 void clear()
15 {
16 mem(head);mem(Head);cnt=Cnt=ans=tot=top=num=0;mem(in_s);mem(dfn);
17 }
18 void add(LL u,LL v,LL val)
19 {
20 to[++cnt]=v;
21 nxt[cnt]=head[u];
22 w[cnt]=val;
23 head[u]=cnt;
24 return ;
25 }
26 void Add(LL u,LL v,LL val)
27 {
28 To[++Cnt]=v;
29 Nxt[Cnt]=Head[u];
30 W[Cnt]=val;
31 Head[u]=Cnt;
32 return ;
33 }
34 void Tarjan(LL x)
35 {
36 dfn[x]=low[x]=++tot;
37 s[++top]=x;
38 in_s[x]=1;
39 for(LL i=head[x];i;i=nxt[i])
40 {
41 LL y=to[i];
42 if(!dfn[y])
43 {
44 Tarjan(y);
45 low[x]=min(low[x],low[y]);
46 }
47 else if(in_s[y])
48 {
49 low[x]=min(low[x],dfn[y]);
50 }
51 }
52 if(low[x]==dfn[x])
53 {
54 num++;
55 while(top)
56 {
57 LL p=s[top--];
58 in_s[p]=0;
59 c[p]=num;
60 if(p==x)break;
61 }
62 }
63 }
64 void toposort()
65 {
66 queue<int>Q;
67 memset(d,0x3f,sizeof(d));
68 d[c[1]]=0;
69 Q.push(c[1]);
70 while(!Q.empty())
71 {
72 LL x=Q.front();Q.pop();
73 for(LL i=Head[x];i;i=Nxt[i])
74 {
75 LL y=To[i];
76 out[y]--;
77 if(W[i]<d[y])
78 {
79 d[y]=W[i];
80 }
81 if(!out[y])Q.push(y);
82 }
83 }
84 return ;
85 }
86 void Build_new()
87 {
88 for(LL i=1;i<=n;i++)
89 for(LL j=head[i];j;j=nxt[j])
90 {
91 LL k=to[j];
92 if(c[i]!=c[k])
93 {
94 Add(c[i],c[k],w[j]);
95 out[c[k]]++;
96 }
97 }
98 }
99 inline LL Rd()
100 {
101 register LL x=0;char c=getchar();
102 while(c>'9'||c<'0')c=getchar();
103 while(c<='9'&&c>='0'){x=x*10+c-'0';c=getchar();}
104 return x;
105 }
106 void work()
107 {
108 while(1)
109 {
110 n=Rd(),m=Rd();
111 if(n==0&&m==0)return ;
112 clear();
113 while(m--)
114 {
115 LL a=Rd(),b=Rd(),c=Rd();
116 a++;b++;
117 add(a,b,c);
118 }
119 Tarjan(1);
120 Build_new();
121 toposort();
122 for(LL i=1;i<=num;i++)ans+=d[i];
123 cout<<ans<<endl;
124 }
125 }
126 }E;
127 int main()
128 {
129 E.work();
130 return 0;
131 }
T3:奇袭(我不会玩甘宁啊) 高难标记
27分算法:维护前缀和扫描
74分算法:维护最大最小值
AC算法:分治
再次膜拜DeepinC
AC代码:
1 #include<cstdio>
2 #include<cstring>
3 #include<iostream>
4 #define MAXN 50005
5 using namespace std;
6 int ans;
7 int w[MAXN],mi[MAXN],ma[MAXN],t[MAXN*2],n;
8 inline int Rd()
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 int solve(int l,int r)
16 {
17 if(l==r)return 1;
18 int mid=l+r>>1;
19 int lans=solve(l,mid),rans=solve(mid+1,r);
20 ans=lans+rans;
21 ma[mid]=mi[mid]=w[mid];
22 ma[mid+1]=mi[mid+1]=w[mid+1];
23 for(int i=mid-1;i>=l;i--)
24 {
25 ma[i]=max(w[i],ma[i+1]);
26 mi[i]=min(w[i],mi[i+1]);
27 }
28 for(int i=mid+2;i<=r;i++)
29 {
30 ma[i]=max(ma[i-1],w[i]);
31 mi[i]=min(mi[i-1],w[i]);
32 }
33 for(int i=mid;i>=l;i--)
34 {
35 int j=ma[i]-mi[i]+i;
36 if(j>mid&&j<=r&&ma[j]<=ma[i]&&mi[j]>=mi[i])ans++;
37 }
38 for(int i=mid+1;i<=r;i++)
39 {
40 int j=i-ma[i]+mi[i];
41 if(j<=mid&&j>=l&&ma[j]<=ma[i]&&mi[j]>=mi[i])ans++;
42 }
43 int head,tail;
44 head=tail=mid+1;
45 for(int i=mid;i>=l;i--)// maxn in left && minn in right mi[j]<mi[i] && ma[j] <ma[i]
46 {
47 while(ma[tail]<=ma[i]&&tail<=r){t[tail+mi[tail]]++;tail++;}
48 while(mi[head]>=mi[i]&&head<=r){t[head+mi[head]]--;head++;}
49 if(t[i+ma[i]]>0)ans+=t[i+ma[i]];
50 }
51 while(head<tail){t[head+mi[head]]--;head++;}
52 while(tail<head){t[tail+mi[tail]]++;tail++;}
53 head=tail=mid;
54 for(int i=mid+1;i<=r;i++)
55 {
56 while(ma[tail]<=ma[i]&&tail>=l){t[tail-mi[tail]+MAXN]++;tail--;}
57 while(mi[head]>=mi[i]&&head>=l){t[head-mi[head]+MAXN]--;head--;}
58 if(t[MAXN+i-ma[i]]>0)ans+=t[MAXN+i-ma[i]];
59 }
60 while(head>tail){t[head-mi[head]+MAXN]--;head--;}
61 while(tail>head){t[tail-mi[tail]+MAXN]++;tail--;}
62 return ans;
63 }
64 int main()
65 {
66 // freopen("da.in","r",stdin);
67 // freopen("my.out","w",stdout);
68 n=Rd();
69 for(int i=1;i<=n;i++)
70 {
71 int a=Rd(),b=Rd();
72 w[a]=b;
73 }
74 printf("%d\n",solve(1,n));
75 return 0;
76 }
77 /*
78 8
79 1 2
80 2 6
81 3 1
82 4 7
83 5 3
84 6 5
85 7 4
86 8 8
87 */
第五次
T1:星际旅行
考试想到正解,没有判连通
AC代码:
1 #include<cstdio>
2 #include<iostream>
3 #include<cstring>
4 #include<vector>
5 using namespace std;
6 const long long MAXN=200005;
7 long long n,m,out[MAXN],s[MAXN],t[MAXN],add,addy;
8 long long C[MAXN][3];
9 long long ans;
10 int f[MAXN],siz[MAXN];
11 bool vst[MAXN];
12 inline long long Rd()
13 {
14 register long long x=0;
15 char c=getchar();
16 while(c>'9'||c<'0')c=getchar();
17 while(c>='0'&&c<='9'){x=x*10+c-48;c=getchar();}
18 return x;
19 }
20 int Get(int a)
21 {
22 return f[a]==a?a:f[a]=Get(f[a]);
23 }
24 void un_ion(int a,int b)
25 {
26 int fa=Get(a),fb=Get(b);
27 f[fa]=fb;
28 siz[fb]+=siz[fa];
29 }
30 int main()
31 {
32 // freopen("out.in","r",stdin);
33 // freopen("a.txt","w",stdout);
34 n=Rd();m=Rd();
35 for(int i=1;i<=n;i++)f[i]=i,siz[i]=1;
36 for(long long i=1;i<=m;i++)
37 {
38 s[i]=Rd();t[i]=Rd();
39 vst[s[i]]=vst[t[i]]=1;
40 if(Get(s[i])!=Get(t[i]))un_ion(s[i],t[i]);
41 if(s[i]==t[i]){add++;ans+=m-add;}
42 else {out[s[i]]++;out[t[i]]++;addy++;}
43 }
44 int xup=0;
45 for(int i=1;i<=n;i++)if(!vst[i])xup++;
46 for(int i=1;i<=n;i++)
47 if(vst[i]&&siz[Get(i)]!=n-xup){cout<<0<<endl;return 0;}
48 else if(vst[i]) break;
49 C[1][0]=C[1][1]=1;
50 for(long long i=2;i<=m;i++)
51 {
52 C[i][0]=1;
53 for(long long j=1;j<=2;j++)
54 C[i][j]=C[i-1][j-1]+C[i-1][j];
55 }
56 for(long long i=1;i<=n;i++)
57 ans+=C[out[i]][2];
58 cout<<ans<<endl;
59 return 0;
60 }
T2:砍树
数论分块。
显然:
辣么移项后易得:(本博猪没有图,自行脑补)。
1 #include<iostream>
2 #include<cstdio>
3 #include<vector>
4 #include<cmath>
5 #include<algorithm>
6 using namespace std;
7 int n;
8 long long m,a[110],maxn;
9 vector<long long>ok;
10 int judge(long long x){
11 long long len=0;
12 for(int i=1;i<=n;i++){
13 int g=ceil((double)a[i]/(double)x);
14 len+=(long long)g;
15 }
16 //cout<<x<<" "<<len<<endl;
17 if(x<=m/len) return 1;
18 return 0;
19 }
20 int main(){
21 scanf("%d%lld",&n,&m);
22 for(int i=1;i<=n;i++) scanf("%lld",&a[i]),m+=a[i],maxn=max(a[i],maxn);
23 // cout<<"fsdf"<<endl;
24 //maxn=1000000;
25 for(long long i=1;i<=m;i++){
26 long long sg=0;
27 for(int j=1;j<=n;j++){
28 sg+=ceil((double)a[j]/(double)i);
29 }
30 //cout<<i<<" "<<sg<<endl;
31 long long sb=m/sg;
32 //cout<<sb<<endl;
33 ok.push_back(sb);
34 i=m/(m/i);
35 }
36 long long ans=0;
37 sort(ok.begin(),ok.end());
38 for(int i=ok.size()-1;i>=0;i--){
39 // cout<<ok[i]<<endl;
40 if(judge(ok[i])){
41 ans=ok[i];
42 break;
43 }
44 }
45 printf("%lld\n",ans);
46 }
T3:超级树
再次借用wd大佬题解
AC代码:
1 #include<cstdio>
2 #include<iostream>
3 #define LL long long
4 #define MAXN 305
5 using namespace std;
6 LL dp[MAXN][MAXN],siz[MAXN];
7 int main()
8 {
9 LL k,mod;
10 scanf("%lld%lld",&k,&mod);
11 dp[1][1]=dp[1][0]=1;
12 siz[1]=1;
13 for(int i=2;i<=k;i++)
14 {
15 if(siz[i-1]<k)siz[i]=siz[i-1]+siz[i-1]+1;
16 else siz[i]=k+1;
17 for(int l=0;l<=min(k,siz[i-1]);l++)
18 for(int r=0;r<=min(k,siz[i-1]);r++)
19 {
20 if(l+r>k)break;
21 LL num=dp[i-1][l]*dp[i-1][r]%mod;
22 if(!num)continue;
23 dp[i][l+r]+=num;if(dp[i][l+r]>=mod)dp[i][l+r]-=mod;
24 dp[i][l+r+1]+=num;if(dp[i][l+r+1]>=mod)dp[i][l+r+1]-=mod;
25 (dp[i][l+r]+=num*(l+r)*2)%=mod;
26 if(l+r>0)
27 (dp[i][l+r-1]+=num*l*r*2)%=mod;
28 if(l+r>0)
29 (dp[i][l+r-1]+=num*(l*(l-1)+r*(r-1)))%=mod;
30 }
31 }
32 cout<<dp[k][1]%mod<<endl;
33 return 0;
34 }