Day5下
Posted wang者归来
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Day5下相关的知识,希望对你有一定的参考价值。
T1
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<queue> #include<cmath> using namespace std; const int N=1010; int n,m,k,p; int to[N],nex[N]; int a[N][N]; int main() { freopen("rotate.in","r",stdin); freopen("rotate.out","w",stdout); scanf("%d%d%d",&n,&p,&k); for(int j=1;j<=n;j++) to[j]=j; for(int i=1;i<=p;i++) { scanf("%d",&m);a[i][0]=m; for(int j=1;j<=m;j++) scanf("%d",&a[i][j]); } for(int i=p;i>=1;i--) { memset(nex,0,sizeof nex);m=a[i][0]; for(int j=2;j<=m;j++) nex[a[i][j-1]]=a[i][j]; nex[a[i][m]]=a[i][1]; for(int j=1;j<=n;j++) if(nex[to[j]]) to[j]=nex[to[j]]; } for(int j=1;j<=n;j++) printf("%d ",to[j]); return 0; }
置换,没学过的话模拟就行。考察理解题意了。
正着做:置换的性质。(不知道也能做)
T2
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<queue> #include<cmath> using namespace std; const int N=1e4+100; int n,a,b,c,d; int q[N]; long long ans; int main() { freopen("range.in","r",stdin); freopen("range.out","w",stdout); scanf("%d%d%d%d%d",&n,&a,&b,&c,&d); for(int i=1;i<=n;i++) scanf("%d",&q[i]); for(int i=1,j;i<=n;i++) { int ans1,ans2; ans1=ans2=q[i]; if(ans1<a||ans2>d) continue; j=i; for(j;j<=n;j++) { ans1&=q[j];ans2|=q[j]; if(ans1<a||ans2>d) break; if(ans1<=b&&ans2>=c) ans++; } } cout<<ans<<endl; return 0; }
先固定左端典,向右搜,查找区间个数。
怎么优化,二分 +倍增。
本来我想’与‘和’或‘是不满足 前缀差等于区间值的性质的。
其实我的想法太狭隘了,仔细想想:无论是’与‘还是’或‘ 都满足两段区间O(1)合成更大区间的性质。
比如f[1,6] & f[3,9], 可以看成f[1,3] & f[3,6]&f[6,9] &f[3,6] 一个数和本身的’‘与’还是本身无影响。
然后就能通过二分把n^n变成nlogn,
T3
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<queue> #include<cmath> using namespace std; const int N=1009; const int P=1e9+7; int n,k; int h[N],nex[N*2],to[N*2],cnt; int w[N],sum[N],tot[N];//子树节点数,根到这的和 int x,y; void add() { scanf("%d%d",&x,&y); to[++cnt]=y,nex[cnt]=h[x],h[x]=cnt; to[++cnt]=x,nex[cnt]=h[y],h[y]=cnt; } int vis[N];int ans; void dfs(int Tot,int Sum,int last) { if(Tot==k) { int ss=Sum; for(int i=1;i<=n;i++) if(vis[i]) for(int j=h[i];j;j=nex[j]) if(!vis[to[j]]) Sum++; Sum=n-1-Sum; ans=(1LL*ans+1LL*(1<<Sum)%P)%P; Sum=ss; } if(Tot>k) return ; for(int i=last;i<=n;i++) if(vis[i]) { int is=0; for(int j=h[i];j;j=nex[j]) if(!vis[to[j]]) { vis[to[j]]=1; dfs(Tot+w[to[j]],Sum+1,i); vis[to[j]]=0; is=1; } } } int main() { freopen("fruit.in","r",stdin); freopen("fruit.out","w",stdout); scanf("%d%d",&n,&k); int is=1; for(int i=1;i<=n;i++) { scanf("%d",&w[i]); if(!w[i]) is=0; } for(int i=1;i<n;i++) add(); vis[1]=1; dfs(w[1],0,1); if(!is) ans--; cout<<ans; return 0; }
说到T3我就不得不吐槽一下,我投入了整套题超过一般的时间,结果0分。
搜索 搜重了,不知道怎么去重。
正解是个背包,f[i][j]表示在i节点及其子树中拿j个果子的方案数,。
以上是关于Day5下的主要内容,如果未能解决你的问题,请参考以下文章