Bzoj [2017 provincial team 10 join test promotion competition 1] (4765 & 4766 & 4767), bzoj4765
Bzoj 4765 -- multipart + dfs sequence + tree array:
Consider chunks. Set ~ N is divided into sqrt (n) blocks, and the number of its ancestors in each block is recorded for each vertex. modify a vertex to enumerate each shard and modify it.
When querying [l, r], if a block is in [l, r], add it to the answer directly. Obviously, only the O (sqrt (n) points are left. Find the dfs order of the tree, and maintain the tree array to obtain the answer by O (logn.
Time complexity O (n * sqrt (n) * logn)
Code:
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 }
Bzoj4765
Bzoj 4766 -- fast power + Fast Multiplication
Conclusion:
The number of spanning trees in a fully bipartite graph is NM-1 * mn-1
Because long is to be created, use a fast multiplication.
Code:
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 }
Bzoj4766
Bzoj4767 -- DP + rejection
For each obstacle point, the number of the two operations from the origin point to its use can be solved by solving the equation.
For an obstacle point, if the number of operations required is x and y, the number of paths from the origin point to it is (x + y )! /(X! * Y !)
Take the number of two operations required for each obstacle point as coordinates.
Sort the obstacle points by x, and f [I] indicates the number of path types from the origin point to the obstacle point I without passing through any obstacle points. Then the DP equation is obtained:
F [I] = g (x [I], y [I])-Σ f [j] * g (x [I]-x [j], y [I]-y [j]), j <I and y [j] <y [I]
G (I, j) indicates the number of solutions from the origin to (I, j.
Pre-process the factorial and inverse factorial.
Time complexity O (n * logn)
Code:
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 }
Bzoj4767