• bzoj [ 2017省队十连测推广赛1 ] ( 4765 && 4766 && 4767 )题解


    bzoj 4765 -- 分块+dfs序+树状数组:

    考虑分块。将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 long
    20 #define ll long long
    21 #define N 100010
    22 #define SN 400
    23 #define lowbit(x) x&-x
    24 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('
    ');
    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 -- 快速幂+快速乘

    一个结论:

    一个完全二分图的生成树个数为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 }
    bzoj4766


    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 }
    bzoj4767


  • 相关阅读:
    Taro、小程序使用定位服务
    Taro项目中设置了设计稿尺寸为375,taro-ui的样式会被放大
    Taro 页面返回携带参数
    Taro + TS 项目取别名配置 alias
    安卓APP 错误:net::ERR_CLEARTEXT_NOT_PERMITTED解决方法
    Springboot定时发送邮件,并附带Excel文件和PDF文件
    通过openssl导入证书到系统证书目录解决安卓7以上系统无法抓包问题
    CentOS 7 安装配置SVN服务器
    解决安装 Docker 慢:使用国内阿里云镜像加速安装
    Redis实战篇(四)基于GEO实现查找附近的人功能
  • 原文地址:https://www.cnblogs.com/gjghfd/p/6516078.html
Copyright © 2020-2023  润新知