zoukankan      html  css  js  c++  java
  • 4.13 BJ集训

    T1 Mobitel

    题目大意:

    一个全是正整数的矩阵,求从左上角到右下角的简单路径有多少条路径上数的乘积$>=K$

    思路:

    由于整数分块,我们设$f(i,j,k)$表示走到$(i,j)$,$k=K/$(路径上数的乘积),的方案数

    然后转移还是正常转移,需要注意把$k--$,因为只能求$>k-1$

     1 #include<iostream>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<algorithm>
     6 #include<cmath>
     7 #include<vector>
     8 #include<queue>
     9 #define rep(i,s,t) for(register int i=(s),i##end=(t);i<=i##end;++i)
    10 #define dwn(i,s,t) for(register int i=(s),i##end=(t);i>=i##end;--i)
    11 #define ren for(int i=fst[x];i;i=nxt[i])
    12 #define ll long long
    13 #define MAXN 305
    14 #define MOD 1000000007
    15 #define pls(a,b) ((a)+(b))%MOD
    16 #define mul(a,b) (1LL*(a)*(b))%MOD
    17 using namespace std;
    18 inline int read()
    19 {
    20     int x=0,f=1;char ch=getchar();
    21     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    22     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    23     return x*f;
    24 }
    25 int n,m,g[MAXN][MAXN],val[3050],id[1001000];int k;
    26 int f[2][MAXN][MAXN*10],tot;
    27 void inc(int &x,int y) {x= (x+y>=MOD)?x+y-MOD:x+y;}
    28 int main()
    29 {
    30     freopen("mobitel.in","r",stdin);freopen("mobitel.out","w",stdout);
    31     n=read(),m=read(),k=read()-1;rep(i,1,n) rep(j,1,m) g[i][j]=read();int c,pos;
    32     rep(i,1,k) pos=k/(k/i),val[++tot]=k/i,i=pos;++tot;rep(i,1,tot) id[val[i]]=i;
    33     f[1][1][id[k/g[1][1]]]=1;rep(t,1,n)
    34     {
    35         c=t&1;rep(i,1,m)
    36             rep(j,1,tot) {inc(f[c][i][id[val[j]/g[t][i]]],f[!c][i][j]);
    37                 if(i<m) inc(f[c][i+1][id[val[j]/g[t][i+1]]],f[c][i][j]);}
    38         memset(f[!c],0,sizeof(f[!c]));
    39     }
    40     printf("%d
    ",f[n&1][m][tot]);
    41 }
    View Code

    T2 transport

    题目大意:

    一个树上,每个点有权值,边权有权值

    求有多少对点对满足对于这条路径任意一个前缀都满足点的权值和>边的权值和

    思路:

    很明显的点分治,对每个分治重心

    搜出每一条从重心开始的链需要之前盈余多少权值才能走到,搜出每一条能走到重心的链到根后盈余多少

    (第一个分别记录$dis$的最低值,第二个记录最小的一个后缀判断能否走到

    排序后双指针,然后容斥一下即可

     1 #include<iostream>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<algorithm>
     6 #include<cmath>
     7 #include<vector>
     8 #include<queue>
     9 #define rep(i,s,t) for(register int i=(s),i##end=(t);i<=i##end;++i)
    10 #define dwn(i,s,t) for(register int i=(s),i##end=(t);i>=i##end;--i)
    11 #define ren for(int i=fst[x];i;i=nxt[i])
    12 #define ll long long
    13 #define inf 2139062143
    14 #define MAXN 100100
    15 #define MOD 1000000007
    16 #define pls(a,b) ((a)+(b))%MOD
    17 #define mul(a,b) (1LL*(a)*(b))%MOD
    18 using namespace std;
    19 inline int read()
    20 {
    21     int x=0,f=1;char ch=getchar();
    22     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    23     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    24     return x*f;
    25 }
    26 int n,m,v[MAXN],fst[MAXN],nxt[MAXN<<1],to[MAXN<<1],val[MAXN<<1];
    27 int mx[MAXN],sz[MAXN],Sum,rt,Mx,vis[MAXN],cnt;
    28 void add(int u,int v,int w) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v,val[cnt]=w;}
    29 void getrt(int x,int pa)
    30 {
    31     mx[x]=0,sz[x]=1;ren if(to[i]^pa&&!vis[to[i]])
    32         getrt(to[i],x),sz[x]+=sz[to[i]],mx[x]=max(mx[x],sz[to[i]]);
    33     mx[x]=max(mx[x],Sum-sz[x]);if(mx[x]<Mx) Mx=mx[x],rt=x;
    34 }
    35 ll g[MAXN],f[MAXN],ans;int ln,len;
    36 void get1(int x,int pa,ll mn,ll dis)
    37 {
    38     g[++len]=mn,dis+=v[x];ren if(to[i]^pa&&!vis[to[i]])
    39         get1(to[i],x,min(dis-val[i],mn),dis-val[i]);
    40 }
    41 void get2(int x,int pa,ll mx,ll dis)
    42 {
    43     if(v[x]-mx>=0) f[++ln]=v[x]+dis;mx-=v[x],dis+=v[x];ren if(to[i]^pa&&!vis[to[i]])
    44         get2(to[i],x,max((ll)val[i],mx+val[i]),dis-val[i]);
    45 }
    46 void calc(int x,int w,ll res=0)
    47 {
    48     int tmp=0,pos=ln;sort(g+1,g+len+1);sort(f+1,f+ln+1);
    49     rep(i,1,len) {while(pos&&g[i]+f[pos]>=0) tmp++,pos--;res+=tmp;}ans+=res*w;
    50 }
    51 void div(int x)
    52 {
    53     vis[x]=1;ln=len=0;get1(x,0,0,0);get2(x,0,0,-v[x]);
    54     calc(x,1);ans--;ren if(!vis[to[i]])
    55     {
    56         ln=len=0;get1(to[i],x,v[x]-val[i],v[x]-val[i]);
    57         get2(to[i],x,val[i],-val[i]);calc(to[i],-1);
    58     }
    59     ren if(!vis[to[i]]) {Sum=sz[to[i]],Mx=n+1;getrt(to[i],x);div(rt);}
    60 }
    61 int main()
    62 {
    63     freopen("transport.in","r",stdin);freopen("transport.out","w",stdout);
    64     n=read();int a,b,c;rep(i,1,n) v[i]=read();
    65     rep(i,2,n) a=read(),b=read(),c=read(),add(a,b,c),add(b,a,c);
    66     Sum=n,Mx=n+1;getrt(1,0);div(rt);printf("%lld
    ",ans);
    67 }
    View Code

    T3

    题目大意:

    $n$个1,要分成$k$段,每一段$[l,r]$的贡献为$frac{r-l+1}{n-l+1}$,求最大贡献

    思路:

    这种恰好$k$段的可以二分

    每一次分段都加上一个二分出来的这个值,判断最优的段数与$k$的关系来二分

    转移的方程是$f_i=f_j+frac{i-j}{n-j}+mid$ 是一个斜率优化的式子

    然后就结束了

     1 #include<iostream>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<algorithm>
     6 #include<cmath>
     7 #include<vector>
     8 #include<queue>
     9 #define rep(i,s,t) for(register int i=(s),i##end=(t);i<=i##end;++i)
    10 #define dwn(i,s,t) for(register int i=(s),i##end=(t);i>=i##end;--i)
    11 #define ren for(int i=fst[x];i;i=nxt[i])
    12 #define ll long long
    13 #define db double
    14 #define MAXN 100100
    15 #define pls(a,b) ((a)+(b))%MOD
    16 #define mul(a,b) (1LL*(a)*(b))%MOD
    17 using namespace std;
    18 inline int read()
    19 {
    20     int x=0,f=1;char ch=getchar();
    21     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    22     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    23     return x*f;
    24 }
    25 int n,k,pre[MAXN],nxt[MAXN],tm[MAXN],tl,hd,q[MAXN];db f[MAXN];
    26 db Y(int i,int j) {return f[i]-f[j]-1.0*i/(n-i)+1.0*j/(n-j);}
    27 db X(int i,int j) {return 1.0/(n-i)-1.0/(n-j);}
    28 int cheq(db x)
    29 {
    30     memset(f,0,sizeof(f));q[hd=tl=1]=0;int t;rep(i,1,n)
    31     {
    32         while(hd<tl&&Y(q[hd],q[hd+1])<=-i*X(q[hd],q[hd+1])) hd++;
    33         t=pre[i]=q[hd],f[i]=f[t]+1.0*(i-t)/(n-t)-x,tm[i]=tm[t]+1,pre[i]=t;
    34         while(hd<tl&&Y(q[tl-1],q[tl])*X(q[tl],i)<Y(q[tl],i)*X(q[tl-1],q[tl])) tl--;
    35         q[++tl]=i;
    36     }return tm[n];
    37 }
    38 int main()
    39 {
    40     freopen("quiz.in","r",stdin);freopen("quiz.out","w",stdout);
    41     n=read(),k=read();db l=0,r=1,mid;
    42     for(int t=0,tmp;mid=(l+r)/2.0,t<=100;t++)
    43     {
    44         if((tmp=cheq(mid))>k) l=mid;
    45         else if(tmp<k) r=mid;else break;
    46     }
    47     printf("%.9lf
    ",f[n]+k*mid);
    48 }
    View Code
  • 相关阅读:
    nullnullConnecting with WiFi Direct 与WiFi直接连接
    nullnullUsing WiFi Direct for Service Discovery 直接使用WiFi服务发现
    nullnullSetting Up the Loader 设置装载机
    nullnullDefining and Launching the Query 定义和启动查询
    nullnullHandling the Results 处理结果
    装置输出喷泉装置(贪心问题)
    数据状态什么是事务?
    停止方法iOS CGD 任务开始与结束
    盘文件云存储——金山快盘
    函数标识符解决jQuery与其他库冲突的方法
  • 原文地址:https://www.cnblogs.com/yyc-jack-0920/p/10701707.html
Copyright © 2011-2022 走看看