bzoj [ 2017省队十连测推广赛1 ] ( 4765 && 4766 && 4767 )题解
来源:互联网 发布:淘宝购买家具退货 编辑:程序博客网 时间:2024/06/03 20:45
bzoj 4765 -- 分块+dfs序+树状数组:bzoj4765bzoj4766bzoj4767
考虑分块。将1~n分成sqrt(n)块,对每个点记录它在每个块中的祖先个数,修改一个点时枚举每一块修改。
查询[l,r]时如果一个块在[l,r]中,直接将其加入答案。显然只剩下O(sqrt(n))个点。求出树的dfs序,用树状数组维护就可以O(logn)求出答案。
时间复杂度O(n*sqrt(n)*logn)
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 using namespace std; 6 inline char nc(){ 7 static char buf[100000],*p1=buf,*p2=buf; 8 if(p1==p2){ 9 p2=(p1=buf)+fread(buf,1,100000,stdin);10 if(p1==p2)return EOF;11 }12 return *p1++;13 }14 inline void Read(int& x){15 char c=nc();16 for(;c<'0'||c>'9';c=nc());17 for(x=0;c>='0'&&c<='9';x=(x<<3)+(x<<1)+c-48,c=nc());18 }19 #define ULL unsigned long long20 #define ll long long21 #define N 10001022 #define SN 40023 #define lowbit(x) x&-x24 struct Edge{25 int t,nx;26 }e[N<<1];27 ULL Sum[SN],c[N],p[N];28 ll k;29 int i,j,n,m,Cnt,s[N][SN],t[SN],S,T,a[N],b[N],f[N],h[N],B[N],Num,Rt,x,y,z;30 inline void Add(int x,int y){31 e[++Num].t=y;e[Num].nx=h[x];h[x]=Num;32 }33 inline void Update_c(int x,int y){34 for(;x<=n;x+=lowbit(x))c[x]+=y;35 }36 inline void Dfs(int x,int F){37 p[x]=a[x];b[x]=++m;if(a[x])Update_c(b[x],a[x]);t[B[x]]++;38 for(int i=1;i<=Cnt;i++)s[x][i]=t[i];39 for(int i=h[x];i;i=e[i].nx)40 if(e[i].t!=F){41 Dfs(e[i].t,x);42 p[x]+=p[e[i].t];43 }44 Sum[B[x]]+=p[x];f[x]=m;t[B[x]]--;45 }46 inline void Update(int x,int y){47 for(int i=1;i<=Cnt;i++)Sum[i]+=1ll*y*s[x][i];48 Update_c(b[x],y);49 }50 inline ULL Query_c(int l,int r){51 ULL Ans=0;52 for(int i=r;i;i-=lowbit(i))Ans+=c[i];53 for(int i=l-1;i;i-=lowbit(i))Ans-=c[i];54 return Ans;55 }56 inline ULL Query(int l,int r){57 ULL Ans=0;58 if(B[l]==B[r]){59 for(int i=l;i<=r;i++)Ans+=Query_c(b[i],f[i]);60 return Ans;61 }62 for(int i=B[l]+1;i<B[r];i++)Ans+=Sum[i];63 for(int i=l;B[i]==B[l];i++)Ans+=Query_c(b[i],f[i]);64 for(int i=r;B[i]==B[r];i--)Ans+=Query_c(b[i],f[i]);65 return Ans;66 }67 char ss[40];68 int Len;69 inline void Print(ULL x){70 if(x==0)putchar(48);71 for(Len=0;x;x/=10)ss[++Len]=x%10;72 for(;Len;)putchar(ss[Len--]+48);putchar('\n');73 }74 int main()75 {76 Read(n);Read(T);S=sqrt((double)n);77 for(i=1;i<=n;i++)B[i]=(i-1)/S+1;Cnt=B[n];78 for(i=1;i<=n;i++)Read(a[i]);79 for(i=1;i<=n;i++){80 Read(x);Read(y);81 if(x==0)Rt=y;else Add(x,y),Add(y,x);82 }83 Dfs(Rt,0);84 while(T--){85 Read(z);Read(x);Read(y);86 if(z&1)Update(x,y-a[x]),a[x]=y;else Print(Query(x,y));87 }88 return 0;89 }
bzoj 4766 -- 快速幂+快速乘
一个结论:
一个完全二分图的生成树个数为nm-1*mn-1
由于要爆long long,要用快速乘。
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 #define ll long long 6 ll n,m,p,a,b; 7 inline ll Ch(ll x,ll y){ 8 ll Ans=0; 9 while(y){10 if(y&1)Ans=(Ans+x)%p;11 x=(x<<1)%p;12 y>>=1;13 }14 return Ans;15 }16 inline ll Pow(ll x,ll y){17 if(y==0)return 1;18 ll Ans=Pow(x,y>>1);19 if(y&1)return Ch(Ch(Ans,Ans),x);20 return Ch(Ans,Ans);21 }22 int main()23 {24 scanf("%lld%lld%lld",&n,&m,&p);25 a=Pow(n,m-1);b=Pow(m,n-1);26 printf("%lld",Ch(a,b));27 }
bzoj4767 -- DP+容斥
对于每个障碍点,从原点到它要使用的两种操作的次数可以用解方程解出。
对于一个障碍点,假如它需要的操作次数分别是x,y,那么从原点到它的路径种数就是(x+y)!/(x!*y!)
将每个障碍点需要的两种操作次数作为坐标。
对障碍点按x排序一遍,令f[i]表示从原点到i号障碍点不经过任何障碍点的路径种数,那么得到DP方程:
f[i]=g(x[i],y[i])-Σf[j]*g(x[i]-x[j],y[i]-y[j]),j<i且y[j]<y[i]
其中g(i,j)表示从原点到(i,j)的方案数。
预处理出阶乘、逆元的阶乘就可以了。
时间复杂度O(n*logn)
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 #define N 510 7 #define Max 1000000 8 #define M 1000000007 9 struct Node{10 int x,y;11 }a[N],A,B;12 int i,j,k,n,m,x,y,f[N],J1[Max],J2[Max],Ni[Max],X,Y;13 inline void Solve(int x,int y){14 int a1=B.x*y-x*B.y,a2=A.y*B.x-A.x*B.y;15 if(a1%a2)return;16 int Ax=a1/a2;17 a1=A.x*y-A.y*x,a2=A.x*B.y-A.y*B.x;18 if(a1%a2)return;19 int Ay=a1/a2;20 if(Ax<0||Ay<0)return;21 if(i<Max&&(Ax>a[1].x||Ay>a[1].y))return;22 a[++m].x=Ax;a[m].y=Ay;23 }24 inline bool Cmp(Node a,Node b){25 return a.x<b.x||(a.x==b.x&&a.y<b.y);26 }27 inline int Work(int x,int y){28 return (1ll*J1[x+y]*J2[x])%M*J2[y]%M;29 }30 int main()31 {32 scanf("%d%d%d%d%d%d%d",&X,&Y,&n,&A.x,&A.y,&B.x,&B.y);33 for(J1[1]=J2[1]=Ni[1]=J1[0]=J2[0]=1,i=2;i<Max;i++)J1[i]=1ll*J1[i-1]*i%M,Ni[i]=1ll*(M-M/i)*Ni[M%i]%M,J2[i]=1ll*J2[i-1]*Ni[i]%M;34 Solve(X,Y);35 if(m==0){printf("0");return 0;}36 for(i=1;i<=n;i++){37 scanf("%d%d",&x,&y);Solve(x,y);38 if(x==X&&y==Y){printf("0");return 0;}39 }40 sort(a+1,a+m+1,Cmp);41 for(i=1;i<=m;i++){42 f[i]=Work(a[i].x,a[i].y);43 for(j=1;j<i;j++)if(a[j].y<=a[i].y)f[i]=(f[i]-1ll*f[j]*Work(a[i].x-a[j].x,a[i].y-a[j].y)%M)%M;44 }45 printf("%d",(f[m]+M)%M);46 return 0;47 }
阅读全文
0 0
- bzoj [ 2017省队十连测推广赛1 ] ( 4765 && 4766 && 4767 )题解
- BZOJ 2017省队十连测推广赛1
- [BZOJ Contest-2017省队十连测推广赛1·T1][BZOJ4765][分块][dfs序]普通计算姬
- [BZOJ Contest-2017省队十连测推广赛1·T3][BZOJ4767][DP][容斥原理]两双手
- [BZOJ Contest-2017省队十连测推广赛1·T2][BZOJ4766][完全二分图的生成树个数]文艺计算姬
- [BZOJ Contest-2017省队十连测推广赛2·T2][BZOJ4771][主席树][dfs序]七彩树
- [BZOJ Contest-2017省队十连测推广赛2·T3][BZOJ4256][DP][Tarjan]推箱子
- [比赛][2017省队十连测推广赛1]
- BZOJ八月月赛题解
- bzoj题解
- bzoj 1218题解
- bzoj 2456 mode 题解
- bzoj 2506 calc 题解
- BZOJ 1257 (题解)
- bzoj 1003 题解
- bzoj 1053 题解
- bzoj 2761 题解
- bzoj 2464 题解
- bzoj1911 [ APIO2010 ] -- 斜率优化DP
- 架构师学长分享
- 3.写出一个程序,接受一个十六进制的数值字符串,输出该数值的十进制字符串。(多组同时输入 )
- bzoj2733 [ HNOI2012 ] -- 并查集+线段树合并
- bzoj2002 [ HNOI2010 ] -- LCT
- bzoj [ 2017省队十连测推广赛1 ] ( 4765 && 4766 && 4767 )题解
- bzoj2049 [ SDOI2008 ] -- LCT
- bzoj2843 -- LCT
- 设置图片圆角加阴影效果
- flex布局(3)
- 51Nod 1228 -- 伯努利数
- bzoj4771 -- dfs序+倍增+主席树
- error MSB600: “cmd.exe”已退出 代码为3
- UnityAI行为------群组行为