10月9-11日连续大翻车实录

10.9

A.

想到组合数……然后就没搞出来……

正解只差一步:容斥原理……

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 const int maxn=(int)1e7+5,mod=998244353;
 7 int n,m,k;
 8 long long po[maxn];
 9 long long qpow(long long x,int tim)
10 {
11     long long tmp=1;
12     for(;tim;tim>>=1,x=x*x%mod)
13         if(tim&1)tmp=tmp*x%mod;
14     return tmp;
15 }
16 long long inv[maxn];
17 long long C(int n,int m)
18 {
19     inv[m]=inv[m]!=0?inv[m]:qpow(po[m],mod-2),inv[n-m]=inv[n-m]!=0?inv[n-m]:qpow(po[n-m],mod-2);
20     return po[n]*inv[m]%mod*inv[n-m]%mod;
21 }
22 int haha()
23 {
24     po[0]=1;for(int i=1;i<=(int)1e7;i++)po[i]=po[i-1]*i%mod;
25     scanf("%d%d%d",&n,&m,&k);
26     if(n>m||1ll*n*k<1ll*m){puts("0");return 0;}
27     long long ans=0;int sgn=1;
28     for(int i=0;i<=n&&m-i*k-1>=n-1;i++)ans=(ans+sgn*C(n,i)*C(m-i*k-1,n-1)%mod+mod)%mod,sgn=-sgn;
29     printf("%lld\n",ans);
30 }
31 int sb=haha();
32 int main(){;}
A

B.

拓扑排序直接水过……

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 const int maxn=(int)1e6+5;
 7 struct node
 8 {
 9     int from,to,next;
10 }edge[maxn<<1];
11 int head[maxn],tot;
12 void addedge(int u,int v)
13 {
14     edge[++tot]=(node){u,v,head[u]};head[u]=tot;
15 }
16 #include <stack>
17 #include <queue>
18 int belong[maxn],size[maxn],cnt,scnt,dfn[maxn],low[maxn],n,m;
19 stack<int>s;
20 void dfs(int root)
21 {
22     dfn[root]=low[root]=++cnt;s.push(root);
23     for(int i=head[root];i;i=edge[i].next)
24     {
25         int v=edge[i].to;
26         if(!dfn[v])dfs(v),low[root]=min(low[root],low[v]);
27         else if(!belong[v])low[root]=min(low[root],dfn[v]);
28     }
29     if(low[root]==dfn[root])
30     {
31         int k;scnt++;
32         do
33         {
34             k=s.top();s.pop();
35             size[scnt]++;belong[k]=scnt;
36         }while(k!=root);
37     }
38 }
39 int dis[maxn],degree[maxn];
40 queue<int>q;
41 int haha()
42 {
43     scanf("%d%d",&n,&m);
44     for(int i=1;i<=m;i++)
45     {
46         int x,y;scanf("%d%d",&x,&y);
47         addedge(x,y);
48     }
49     for(int i=1;i<=n;i++)
50         if(!dfn[i])dfs(i);
51     memset(head,0,sizeof(head));
52     for(int i=1;i<=m;i++)
53     {
54         int u=edge[i].from,v=edge[i].to;
55         if(belong[u]!=belong[v])addedge(belong[u],belong[v]),degree[belong[v]]++;
56     }
57     int ans=0;
58     for(int i=1;i<=scnt;i++)
59         if(!degree[i])dis[i]=size[i],q.push(i),ans=max(ans,dis[i]);
60     while(!q.empty())
61     {
62         int now=q.front();q.pop();
63         for(int i=head[now];i;i=edge[i].next)
64         {
65             int v=edge[i].to;degree[v]--;dis[v]=max(dis[v],dis[now]+size[v]);
66             if(!degree[v])ans=max(ans,dis[v]),q.push(v);
67         }
68     }
69     printf("%d\n",ans);
70 }
71 int sb=haha();
72 int main(){;}
B

C.

不可做啊……至今没人过……

10.10

A.

妈的智障……瞎模拟一分没有……完全没注意到超过17一定可以实现……然后就可以大大减少枚举量……

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=1000005;
 4 int n,a[18*maxn],b[18*maxn],f[18*maxn],A[maxn],B[maxn],id[maxn];
 5 inline bool cmp(const int &x,const int &y)
 6 {
 7     return B[x]<B[y];
 8 }
 9 int haha()
10 {
11     long long m;scanf("%d%lld",&n,&m);
12     int ans=0;
13     for(int i=1;i<=n;i++)scanf("%d%d",&A[i],&B[i]),id[i]=i;
14     sort(id+1,id+n+1,cmp);
15     for(int i=1;i<=n;i++)
16     {
17         if(B[id[i]]-B[id[i-1]]>17)b[i]=b[i-1]+18;else b[i]=b[i-1]+B[id[i]]-B[id[i-1]];
18         a[b[i]]+=A[id[i]];
19     }
20     for(int i=1;i<=b[n];i++)
21     {
22         if(i==1||i==2||i==3||i==5||i==6||i==9||i==10||i==13||i==17)continue;
23         f[i]=a[i];
24         if(i>=7)f[i]+=max(f[i-4],f[i-7]);
25         else if(i>=4)f[i]+=f[i-4];
26         ans=max(ans,f[i]);
27     }
28     printf("%d\n",ans);
29 }
30 int sb=haha();
31 int main(){;}
A

B.

想过多种策略……然而当时一一否决,包括正解……最后发现其实根本不需要考虑路径长度和是否真的是那个值……因为最终一定合法值最小……

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=35;
 4 int f[maxn][maxn][1775],a[maxn][maxn];
 5 int haha()
 6 {
 7     int t;scanf("%d",&t);
 8     while(t--)
 9     {
10         int n,m;scanf("%d%d",&n,&m);
11         for(int i=1;i<=n;i++)
12             for(int j=1;j<=m;j++)scanf("%d",&a[i][j]);
13         memset(f,0x3f,sizeof(f));f[1][1][a[1][1]]=a[1][1]*a[1][1];
14         for(int i=1;i<=n;i++)
15             for(int j=1;j<=m;j++)
16                 for(int k=0;k<=1770-a[i][j];k++)
17                 {
18                     f[i+1][j][k+a[i+1][j]]=min(f[i+1][j][k+a[i+1][j]],f[i][j][k]+a[i+1][j]*a[i+1][j]);
19                     f[i][j+1][k+a[i][j+1]]=min(f[i][j+1][k+a[i][j+1]],f[i][j][k]+a[i][j+1]*a[i][j+1]);
20                 }
21         int ans=0x7f7f7f7f;
22         for(int sum=1;sum<=1770;sum++)
23         {
24             if(f[n][m][sum]==0x3f3f3f3f)continue;
25             ans=min(ans,(n+m-1)*f[n][m][sum]-sum*sum);
26         }
27         printf("%d\n",ans);
28     }
29 }
30 int sb=haha();
31 int main(){;}
B

C.

树归写挂……一份没有……

最后发现最后四个二进制位记录个数就过了的我眼泪掉下来……

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=100005;
 4 struct node
 5 {
 6     int from,to,dis,next;
 7 }edge[maxn<<1];
 8 int head[maxn],tot;
 9 void addedge(int u,int v,int w)
10 {
11     edge[++tot]=(node){u,v,w,head[u]};head[u]=tot;
12 }
13 int n,m;
14 int W[20];
15 int dis[maxn],size[maxn],Q[maxn][20],delta[maxn],sonnum[maxn][20],f[maxn];
16 void dfs1(int root,int fa)
17 {
18     size[root]=1;
19     for(int i=head[root];i;i=edge[i].next)
20     {
21         int v=edge[i].to;int tmp=0;
22         if(v!=fa)
23         {
24             dfs1(v,root);
25             size[root]+=size[v];dis[root]+=dis[v];
26             for(int j=0;j<16;j++)Q[root][j+edge[i].dis&15]+=Q[v][j],sonnum[v][j+edge[i].dis&15]+=Q[v][j],tmp+=W[j]*Q[v][j];
27             Q[root][edge[i].dis&15]++,sonnum[v][edge[i].dis&15]++;
28             f[root]+=f[v]-tmp+size[v]*edge[i].dis;
29         }
30     }
31     for(int i=0;i<16;i++)delta[root]+=W[i]*Q[root][i];
32     f[root]+=delta[root];
33 }
34 int g[maxn],P[maxn][20];
35 void dfs2(int root,int fa)
36 {
37     for(int i=head[root];i;i=edge[i].next)
38     {
39         int v=edge[i].to;
40         if(v!=fa)
41         {
42             int tmp=0,tmp2=0;
43             for(int j=0;j<16;j++)
44             {
45                 tmp+=W[j]*Q[v][j];
46                 P[v][j+edge[i].dis&15]+=P[root][j];
47                 P[v][j+edge[i].dis&15]+=Q[root][j]-sonnum[v][j];
48                 tmp2+=W[j]*P[root][j];
49             }
50             P[v][edge[i].dis&15]++;
51             int convey=f[root]-delta[root]-(f[v]-tmp+edge[i].dis*size[v]);
52             g[v]=convey+g[root]-tmp2+(n-size[v])*edge[i].dis;
53             for(int j=0;j<16;j++)g[v]+=P[v][j]*W[j];
54             dfs2(v,root);
55         }
56     }
57 }
58 int haha()
59 {
60     scanf("%d%d",&n,&m);
61     for(int i=1;i<n;i++)
62     {
63         int x,y,z;scanf("%d%d%d",&x,&y,&z);
64         addedge(x,y,z);addedge(y,x,z);
65     }
66     for(int i=0;i<16;i++)W[i]=(i^m)-i;
67     dfs1(1,0);dfs2(1,0);
68     for(int i=1;i<=n;i++)printf("%d\n",f[i]+g[i]);
69 }
70 int sb=haha();
71 int main(){;}
C

10.11     ——真·翻车

A.

没判重飞了70分……100->30

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=100005;
 4 int a[maxn],f[maxn],n;
 5 multiset<int>S;
 6 int gcd(int a,int b){return !b?a:gcd(b,a%b);}
 7 int haha()
 8 {
 9     scanf("%d",&n);
10     for(int i=1;i<=n;i++)scanf("%d",&a[i]);
11     f[1]=1;S.insert(a[1]);
12     int gongcha=0;
13     for(int i=2;i<=n;i++)
14     {
15         if(S.count(a[i])){S.clear();gongcha=0;f[i]=f[i-1]+1;S.insert(a[i]);continue;}
16         S.insert(a[i]);
17         multiset<int>::iterator it=S.lower_bound(a[i]),it2=it,it3=it;
18         if(it!=S.begin())--it;
19         ++it2;if(it2==S.end())--it2;
20         if(it2==it3||it==it3)
21         {
22             gongcha=gcd(gongcha,(*it2)-(*it));
23             if(gongcha<=1){S.clear();gongcha=0;S.insert(a[i]);f[i]=f[i-1]+1;continue;}
24             f[i]=f[i-1];continue;
25         }
26         int bigger=(*it2),smaller=(*it);
27         gongcha=gcd(gongcha,bigger-a[i]);gongcha=gcd(gongcha,a[i]-smaller);
28         if(gongcha<=1){S.clear();gongcha=0;S.insert(a[i]);f[i]=f[i-1]+1;continue;}
29         f[i]=f[i-1];
30     }
31     printf("%d\n",f[n]);
32 }
33 int sb=haha();
34 int main(){;}
A

B.

没考虑集合大小为1时要建双向边日飞100分……100->0

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=500005;
 4 struct node
 5 {
 6     int from,to,next;
 7 }edge[maxn];
 8 int head[maxn],tot;
 9 void addedge(int u,int v)
10 {
11     edge[++tot]=(node){u,v,head[u]};head[u]=tot;
12 }
13 int n,m,num,tim,vis[maxn];
14 int dfs(int now,int tar)
15 {
16     if(now==tar)return 1;vis[now]=tim;
17     for(int i=head[now];i;i=edge[i].next)
18     {
19         int v=edge[i].to;
20         if(vis[v]!=tim)
21             if(dfs(v,tar))return 1;
22     }
23     return 0;
24 }
25 int haha()
26 {
27     scanf("%d%d",&n,&m);num=n;
28     while(m--)
29     {
30         int opt;scanf("%d",&opt);
31         if(!opt)
32         {
33             num++;int dir,sum;scanf("%d%d",&dir,&sum);
34             for(int i=1;i<=sum;i++)
35             {
36                 int x;scanf("%d",&x);
37                 if(sum==1){addedge(num,x),addedge(x,num);break;}
38                 if(!dir)addedge(num,x);else addedge(x,num);
39             }
40         }
41         else
42         {
43             tim++;int fr,to;scanf("%d%d",&fr,&to);
44             printf("%d\n",dfs(fr,to));
45         }
46     }
47 }
48 int sb=haha();
49 int main(){;}
B

C.

口胡了一个完全不对的单调队列结果操作完全错误炸飞50分……60->10

实际上这个东西根本不能用单调队列……因为可以构造出某些数据,f数组极小,B数组极大,结果在更新单调队列时直接被扔掉,但其实后面它还可能成为最优解……(不过这样数据很难造吧……对拍两千多组数据都没错……)

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=500005;
 4 struct node
 5 {
 6     int from,to,next;
 7 }edge[maxn];
 8 int head[maxn],tot;
 9 void addedge(int u,int v)
10 {
11     edge[++tot]=(node){u,v,head[u]};head[u]=tot;
12 }
13 int n,m,num,tim,vis[maxn];
14 int dfs(int now,int tar)
15 {
16     if(now==tar)return 1;vis[now]=tim;
17     for(int i=head[now];i;i=edge[i].next)
18     {
19         int v=edge[i].to;
20         if(vis[v]!=tim)
21             if(dfs(v,tar))return 1;
22     }
23     return 0;
24 }
25 int haha()
26 {
27     scanf("%d%d",&n,&m);num=n;
28     while(m--)
29     {
30         int opt;scanf("%d",&opt);
31         if(!opt)
32         {
33             num++;int dir,sum;scanf("%d%d",&dir,&sum);
34             for(int i=1;i<=sum;i++)
35             {
36                 int x;scanf("%d",&x);
37                 if(sum==1){addedge(num,x),addedge(x,num);break;}
38                 if(!dir)addedge(num,x);else addedge(x,num);
39             }
40         }
41         else
42         {
43             tim++;int fr,to;scanf("%d%d",&fr,&to);
44             printf("%d\n",dfs(fr,to));
45         }
46     }
47 }
48 int sb=haha();
49 int main(){;}
C

我的分啊……………………………………………………………………

posted @ 2017-10-11 20:28  ccc000111  阅读(244)  评论(0编辑  收藏  举报