9.1 正睿提高2

目录

  • 2018.9.1 Test

    • A(凸壳 单调栈)
    • B(思路 独立)
    • C
    • 考试代码
      • A
      • B
      • C

2018.9.1 Test

时间:3.5h
实际得分:40+50+20

比赛链接

T1直接忽略了,刚了3小时T2(暴力写法不好,直接乘逆元就行→_→),算是有点成果吧。。
然后20分钟写完T1、T3。感觉T3也算可做的。

A(凸壳 单调栈)

题目链接

注意到\(c_i=0\),即二次函数对称轴都为y轴,但是好像还是很难做。。
但是这样我们可以把一个x提出来,变成\(x(ax+b)\)。
所以\(x>0\)时,我们要求\(\max{a_i*x+b_i}\),即维护一个上凸壳;\(x<0\)时,维护一个下凸壳。
求法都一样,还是对斜率排序,用单调栈维护。更新时看i,sk[top],sk[top-1]间的关系。
求出凸壳后,可以在这些直线中二分出最大最小值是哪条直线。可以将求min时的直线乘-1,询问时再取反,就可以只写一个Find_Max的二分了(随意)。

还是用上/下凸壳指直线斜率递增/递减吧(凸函数)。。和图形反着。

只求了个上凸壳,在上面二分最小值直线竟然是对的。。嗯 好像是对的。。

#include <cstdio>
#include <cctype>
#include <algorithm>
//#define gc() getchar()
#define MAXIN 300000
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
#define k first
#define b second
#define mp std::make_pair
#define pr std::pair<int,int>
typedef long long LL;
const int N=5e5+5;

int n;
pr l[N],lu[N],ld[N];
LL ans[32330*2];
char IN[MAXIN],*SS=IN,*TT=IN;

inline int read()
{
    int now=0,f=1;register char c=gc();
    for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
    for(;isdigit(c);now=now*10+c-'0',c=gc());
    return now*f;
}
inline bool Check(pr a,pr b,pr c){//p(a&b) is on the left of p(b&c)
    return 1ll*(b.b-a.b)*(c.k-b.k)<=1ll*(b.b-c.b)*(a.k-b.k);
}
void Convex(pr *sk,int &top)
{
    sk[top=1]=l[1];
    for(int i=2; i<=n; ++i)
    {
        if(l[i].k==l[i-1].k) continue;
        while(top>1 && Check(l[i],sk[top],sk[top-1])) --top;
        sk[++top]=l[i];
    }
}
#define F(i,x) (1ll*line[i].k*x+line[i].b)
inline LL Find_Min(pr *line,int r,int x)
{
    int l=1,mid;
    while(l<r)
    {
        mid=l+r>>1;
        if(F(mid,x)<F(mid+1,x)) r=mid;
        else l=mid+1;
    }
    return 1ll*x*F(l,x);
}
inline LL Find_Max(pr *line,int r,int x)
{
    int l=1,mid;
    while(l<r)
    {
        mid=l+r>>1;
        if(F(mid,x)>F(mid+1,x)) r=mid;
        else l=mid+1;
    }
    return 1ll*x*F(l,x);
}

int main()
{
    n=read(); int Q=read();
    for(int i=1,t; i<=n; ++i) t=read(),l[i]=mp(t,read());
    std::sort(l+1,l+1+n);
    int cntu=0;
    Convex(lu,cntu);//, Convex(ld,cntd);
    ans[32323]=0;//x=0
    for(int x; Q--; )
    {
        x=read();
        if(ans[x+32323]) printf("%lld\n",ans[x+32323]);
        else if(x<0) printf("%lld\n",ans[x+32323]=Find_Min(lu,cntu,x));
        else printf("%lld\n",ans[x+32323]=Find_Max(lu,cntu,x));
    }
    return 0;
}

B(思路 独立)

题目链接

答案就是所有元素期望被减的次数。(当然\(a_1\)是一定会被减掉的)
考虑某一局面,\(i(i\neq1)\)被减的期望次数是多少。所有元素被减的概率都是相同的。因为次数只与当前的\(a_1,a_i\)有关,且无论其它元素怎么变,1和i被减的概率都相同。
即其它元素对考虑它们没有影响,这个问题就等价于只有两个元素的原问题。(等价很厉害啊,与其它无关且概率相同概率就都是\(\frac{1}{2}\)了)
因此元素之间是独立的。对每个\(a_i\)计算答案求和就可以了。
对于只有两个元素的问题,相当于从点\((a_1,a_2)\)出发,每次等概率向左或向下走一步,直至走到坐标轴。若走到\((0,x)\),则对答案贡献\(a_2-x\);若走到\((x,0)\),则对答案贡献\(a_2\)。
或者考虑枚举\(a_2\)在\(a_1\)被减到0前减了多少次。
\[\sum_{i=0}^{a_2-1}i*\frac{C_{a_1-1+i}^i}{2^{a_1+i}}+a_2(1-\sum_{i=0}^{a_2-1}\frac{C_{a_1-1+i}^i}{2^{a_1+i}})\]
前面是\(a_2\)未被减至0的期望次数,后面是被减至0的期望次数(概率用\(1-\sum_{i=0}^{a_2-1}\frac{C_{a_1-1+i}^i}{2^{a_1+i}}\)就可以啊)。
\(a_2\)每次增加1,前后都只会增加1项。算的时候直接用到\(a_2\)的前缀和也对,因为前后正好消掉。
复杂度\(O(a+n)\)。

#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
#define mod 323232323
typedef long long LL;
const int N=1e6+5;

int n,A[N>>1],fac[N],inv[N],inv2[N],f[N],p[N];

#define C(n,m) (1ll*fac[(n)]*inv[(m)]%mod*inv[(n)-(m)]%mod)
inline int read()
{
    int now=0;register char c=gc();
    for(;!isdigit(c);c=gc());
    for(;isdigit(c);now=now*10+c-'0',c=gc());
    return now;
}
inline int FP(int x,int k)
{
    int t=1;
    for(; k; k>>=1,x=1ll*x*x%mod)
        if(k&1) t=1ll*t*x%mod;
    return t;
}

int main()
{
    n=read(); int mx=0;
    for(int i=1; i<=n; ++i) mx=std::max(mx,A[i]=read());
    int a1=A[1], lim=a1+mx; fac[0]=1;
    for(int i=1; i<=lim; ++i) fac[i]=1ll*fac[i-1]*i%mod;
    inv[lim]=FP(fac[lim],mod-2);
    for(int i=lim-1; ~i; --i) inv[i]=1ll*inv[i+1]*(i+1)%mod;
    int i2=FP(2,mod-2); inv2[0]=1;
    for(int i=1; i<=lim; ++i) inv2[i]=1ll*inv2[i-1]*i2%mod;//2^{-i}

    p[0]=inv2[a1];
    for(int i=1; i<=mx; ++i)
    {
        p[i]=1ll*C(a1+i-1,i)*inv2[a1+i]%mod, f[i]=1ll*i*p[i]%mod;
        p[i]+=p[i-1], p[i]>=mod&&(p[i]-=mod);
        f[i]+=f[i-1], f[i]>=mod&&(f[i]-=mod);
    }
    LL ans=a1;
    for(int i=2; i<=n; ++i) ans+=f[A[i]/*-1*/]+1ll*A[i]*(mod+1-p[A[i]/*-1*/])%mod;
    printf("%d\n",(int)(ans%mod));

    return 0;
}

C

题目链接

考试代码

A

#include <cstdio>
#include <cctype>
#include <algorithm>
//#define gc() getchar()
#define MAXIN 300000
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
typedef long long LL;
const int N=5e5+5;

int n,Q,A[N],B[N];
LL ans[32323*4];
char IN[MAXIN],*SS=IN,*TT=IN;

inline int read()
{
    int now=0,f=1;register char c=gc();
    for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
    for(;isdigit(c);now=now*10+c-'0',c=gc());
    return now*f;
}
inline LL F(int x)
{
    int xx=x*x;
    LL res=1ll*A[1]*xx+(LL)B[1]*x;
    for(int i=2; i<=n; ++i) res=std::max(res,1ll*A[i]*xx+(LL)B[i]*x);
    return res;
}

int main()
{
//  freopen(".in","r",stdin);
//  freopen(".out","w",stdout);

    n=read(), Q=read();
    for(int i=1; i<=n; ++i) A[i]=read(),B[i]=read();
    for(int i=1,x; i<=Q; ++i)
    {
        x=read();
        if(ans[x+32323]) printf("%lld\n",ans[x+32323]);
        else printf("%lld\n",ans[x+32323]=F(x));
    }
    return 0;
}

B

#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
#define mod 323232323
typedef long long LL;
const int N=5e5+5;

int n,A[N],fac[N<<1],inv[N<<1],i2[N<<1];
struct Fraction
{
    LL x,y;
    Fraction() {x=0, y=1;}
    Fraction(LL x,LL y):x(x),y(y) {}
    LL Gcd(LL x,LL y){
        return y?Gcd(y,x%y):x;
    }
    void Exgcd(LL a,LL b,LL &x,LL &y)
    {
        if(!b) x=1, y=0;
        else Exgcd(b,a%b,y,x),y-=a/b*x;
    }
    void Fix() {LL g=Gcd(x,y); x/=g, y/=g;}
    Fraction operator +(const Fraction &f)
    {
        LL a=x*f.y+y*f.x,b=y*f.y,g=Gcd(a,b);
//      printf("%I64d/%I64d + %I64d/%I64d = %I64d/%I64d\n",x,y,f.x,f.y,a/g,b/g);
        return Fraction(a/g,b/g);
    }
    Fraction operator +(LL f)
    {
        LL a=f*y+x,g=Gcd(a,y);
        return Fraction(a/g,y/g);
    }
    Fraction operator *(LL f)
    {
        LL a=x*f,g=Gcd(a,y);
        return Fraction(a/g,y/g);
    }
//  Fraction operator *(const Fraction &f)
//  {
//      LL a=x*f.x,b=y*f.y,g=Gcd(a,b);
//      return Fraction(a/g,b/g);
//  }
    void Print()
    {
        LL a,b; Exgcd(y,mod,a,b);
        a=(a%mod+mod)%mod;//!
//      printf("\n%I64d/%I64d=",x,y);
        printf("%d\n",(int)(a*x%mod));
    }
}Ans;

inline int read()
{
    int now=0;register char c=gc();
    for(;!isdigit(c);c=gc());
    for(;isdigit(c);now=now*10+c-'0',c=gc());
    return now;
}
inline int FP(int x,int k)
{
    int t=1;
    for(; k; k>>=1,x=1ll*x*x%mod)
        if(k&1) t=1ll*t*x%mod;
    return t;
}
void DFS(int x,int t,LL p)
{
    if(!A[1])
    {
//      printf("%d %d*1/%I64d\n",x,t,p);
        Ans=Ans+Fraction(1,p)*t;
        return;
    }
    for(int i=1; i<=n; ++i)
        if(A[i]) --A[i], DFS(x+!A[i],t+1,p*(n-x)%mod), ++A[i];
}
bool Check2()
{
    for(int i=1; i<=n; ++i) if(A[i]>1) return 0;
    return 1;
}
#define C(n,m) (1ll*fac[(n)]*inv[(m)]%mod*inv[(n)-(m)]%mod)
//int c[1005][1005];
//int C(int n,int m) {return c[n][m];}
void Solve3()
{
//  c[0][0]=1;
//  for(int i=1; i<1000; ++i)
//  {
//      c[i][0]=c[i][i]=1;
//      for(int j=1; j<i; ++j)
//          c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;
//  }
    int a1=A[1], a2=A[2], lim=a1+a2; fac[0]=1;
    for(int i=1; i<=lim; ++i) fac[i]=1ll*fac[i-1]*i%mod;
    inv[lim]=FP(fac[lim],mod-2), inv[0]=1;
    for(int i=lim-1; i; --i) inv[i]=1ll*inv[i+1]*(i+1)%mod;
    int inv2=FP(2,mod-2); i2[0]=1;
    for(int i=1; i<=lim; ++i) i2[i]=1ll*i2[i-1]*inv2%mod;//2^{-i-1}
    LL ans=0;
    for(int i=0; i<a2; ++i)
        ans+=1ll*C(a1+i-1,i)*(a1+i)%mod*i2[a1+i]%mod;
    for(int i=a2; i<lim; ++i)
        ans+=1ll*C(i-1,a2-1)*lim%mod*i2[i]%mod;
    printf("%d\n",(int)(ans%mod));
}

int main()
{
//  freopen("B.in","r",stdin);

    n=read();
    for(int i=1; i<=n; ++i) A[i]=read();
    if(n==1) return printf("%d\n",A[1]),0;
//  DFS(0,0,1); Ans.Print();
    if(n<=5&&A[1]<=5&&A[2]<=5) {DFS(0,0,1); Ans.Print(); return 0;}
    if(Check2()) {Fraction(n+1,2).Print(); return 0;}
    if(n==2) {Solve3(); return 0;}
    printf("%d\n",202020207);

    return 0;
}

C

#include <cstdio>
#include <cctype>
#include <algorithm>
//#define gc() getchar()
#define MAXIN 300000
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
typedef long long LL;
const int N=3e5+5;

int n,Q,A[N],dis[N],Enum,H[N],nxt[N<<1],to[N<<1],top[N],dep[N],fa[N],sz[N],son[N],dgr[N];
LL Ans[N];
char IN[MAXIN],*SS=IN,*TT=IN;

inline int read()
{
    int now=0;register char c=gc();
    for(;!isdigit(c);c=gc());
    for(;isdigit(c);now=now*10+c-'0',c=gc());
    return now;
}
inline void AddEdge(int u,int v)
{
    ++dgr[v], to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum;
    ++dgr[u], to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum;
}
inline int LCA(int u,int v)
{
    while(top[u]!=top[v]) dep[top[u]]>dep[top[v]]?u=fa[top[u]]:v=fa[top[v]];
    return dep[u]>dep[v]?v:u;
}
void DFS1(int x)
{
    int mx=0; sz[x]=1;
    for(int v,i=H[x]; i; i=nxt[i])
        if((v=to[i])!=fa[x])
        {
            dis[v]=dis[x]+1, fa[v]=x, dep[v]=dep[x]+1, DFS1(v), sz[x]+=sz[v];
            if(mx<sz[v]) mx=sz[v], son[x]=v;
        }
}
void DFS2(int x,int tp)
{
    top[x]=tp;
    if(son[x])
    {
        DFS2(son[x],tp);
        for(int i=H[x]; i; i=nxt[i])
            if(to[i]!=fa[x]&&to[i]!=son[x]) DFS2(to[i],to[i]);
    }
}
void DFS(int x,int f,int d)
{
    Ans[x]=Ans[f]+(A[x]|d);
    for(int i=H[x]; i; i=nxt[i])
        if(to[i]!=f) DFS(to[i],x,d+1);
}
void Spec()
{
    DFS(1,1,0);
    for(int u,v; Q--; )
    {
        u=read(), v=read();
        if(u==1) std::swap(u,v);
        printf("%lld\n",Ans[u]);
    }
}

int main()
{
//  freopen("C.in","r",stdin);
//  freopen(".out","w",stdout);

    n=read(), Q=read();
    for(int i=1; i<=n; ++i) A[i]=read();
    for(int i=1; i<n; ++i) AddEdge(read(),read());
    if(n>5000) {Spec(); return 0;}
    DFS1(1), DFS2(1,1);
    for(int u,v,w; Q--; )
    {
        u=read(), v=read(), w=LCA(u,v);
        LL ans=A[w]|(dis[u]-dis[w]);
        for(int x=u,d=0; x!=w; x=fa[x],++d) ans+=A[x]|d;
        for(int x=v,d=dis[u]+dis[v]-(dis[w]<<1); x!=w; x=fa[x],--d) ans+=A[x]|d;
        printf("%lld\n",ans);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/SovietPower/p/9574547.html

时间: 2024-08-30 11:46:23

9.1 正睿提高2的相关文章

9.22 正睿提高4

目录 2018.9.22 正睿提高5 A 数组计数(DP) B 旅行(思路) C 进化(思路 二进制拆分) 考试代码 B C 2018.9.22 正睿提高5 时间:3.5h 期望得分:100+80+30 实际得分:100+80+30 比赛链接 T2一直以为类似某道虚树题(SDOI2015)..到最后只想写暴力(写了暴力也该想到了啊 但是已经在划水了). A 数组计数(DP) 题目链接 DP.前缀和优化一下就行了. 刚开始滚动数组又少清空了mmp.. #include <cstdio> #inc

正睿提高组2017模拟题二T2

不会线性的,但是群里有个大神,发现用可以用80分的复杂度写出100分的效果,于是.... 考虑每次加入一条边,我们用f[x][j]表示加入第i条边后,当前的并查集x中,第j个点的父亲.那么如何加呢?假设当前第i条边的两端点为u和v,如果第x个并查集中u和v联通那么很明显,它不可以再加到这个并查集中(每个并查集维护的就是一个极大森林),然后就往后找,直到能找到一个x使得其中u和v是不连通的为止(肯定能找到,因为如果已有的都已经连通,说明前x个极大森林中都无法删去这条边,所以再构建一个新的并查集就好

正睿提高组2017模拟题三T1

听了很久又看了很久别人的程序才听懂,于是乎记录一下防止以后忘记. 好啦,假设当前 l-1=5,r=7;那如果学习过树状数组的话就知道题目中的操作如果转换为二进制的话 对于l-1来说他的二进制是101,所以会被加上-1的位置是101和100,r的二进制是111,所以会被加上1的位置是111,110,100 所以可以发现最后更新的位置是l-1的二进制的1的个数+r的二进制的1的个数-2*l-1和r都会更新的位置. 而l-1和r减1都会更新的位置的个数是它们两个二进制的最长公共前缀的1的个数(当然,前

正睿OI国庆DAY2:图论专题

正睿OI国庆DAY2:图论专题 dfs/例题 判断无向图之间是否存在至少三条点不相交的简单路径 一个想法是最大流(后来说可以做,但是是多项式时间做法 旁边GavinZheng神仙在谈最小生成树 陈主力说做法是dfs 首先两个点一定在点双联通分量里 点双是简单环,只有两条,不存在 猜测其他情况存在三条 双联通分量分解 输出情况可以用dfs树判,讨论非树边覆盖情况 内包含 下面分叉连到上面 相交 输出点即可 BFS/例题 BFS树没有跳跃边 计数/动态规划有用吧 树上bfs序好像可以判断距离? 边权

正睿OI DAY3 杂题选讲

正睿OI DAY3 杂题选讲 CodeChef MSTONES n个点,可以构造7条直线使得每个点都在直线上,找到一条直线使得上面的点最多 随机化算法,check到答案的概率为\(1/49\) \(n\leq k^2\) 暴力 \(n\geq k^2\),找点x,求直线l经过x,且点数最多,点数\(\geq k+1\),递归,否则再找一个 One Point Nine Nine 现在平面上有\(n\)个点,已知有一个常数\(D\). 任意两点的距离要么\(\leq D\),要么\(\geq 1.

[题解向] 正睿Round435

10.14 Link 唔,这一场打得不好.获得了\(\rm 75pts/300pts\)的得分,但是居然可以获得\(\rm 27/69\)的名次,也不至于不满意--毕竟是真不会233 \(\rm T1\) 大概就是字典序那个地方比较爆炸-- 于是就考虑奇数开头和偶数开头分开做,对于每种情况调整成一个合法最小代价序列.这个地方有一个贪心,原来在前面的依旧会在前面,在后面的也还会在后面,扫一遍就做完了. 这个贪心里面蕴含着一个性质.\(now_i<i,now_j<j\),即"同向换&qu

[题解向] 正睿Round409

\(\rm Link\) 然而泥萌没有权限是看不了题目的233. \(\rm T1\) 大概就是个map,脑残出题人认为(x,x)不属于有序二元组,我可qtmd.于是只拿了\(\rm 60pts\) int main(){ ios_base :: sync_with_stdio(false) ; cin.tie(0), cout.tie(0) ; cin >> N >> P ; int i ; for (i = 1 ; i <= N ; ++ i) cin >>

正睿多校联盟训练Week5

T1 Problem A. 阿瓦的海报输入文件: poster.in输出文件: poster.out时间限制: 1 second空间限制: 512 megabytes阿瓦为了宣传她的影展,准备画一张海报张贴在幻想镇的各个角落.她为了让海报引人注目,已经在图案.背景和排版上费了很大的工夫.但这时她接到一个来自印刷厂的通知:印刷厂的纸不够了,本来答应给阿瓦定做的海报不能达到预期的尺寸.印刷厂表示,剩下的纸最多能够承担每张海报的面积为 S.而阿瓦认为,海报的面积应当是越大越好,所以阿瓦决定,就将每张海

正睿多校联盟训练Week6

并没有参加 Problem A.阿瓦分蛋糕输入文件: cake.in输出文件: cake.out时间限制: 1 second空间限制: 512 megabytes阿瓦为了庆祝自己自己成长为了一只可爱的小猫,决定提前过生日!她觉得,在这一年当中帮助过他最多的就是阿卡和烤乐滋了,于是决定这次只请阿卡和烤乐滋两个人吃蛋糕.阿瓦买了一个 n × m 的蛋糕,她打算分给三个人吃,同时她切蛋糕的时候为了美观,只会在整块的蛋糕上一划到底.也就是说,她如果在蛋糕上切了一刀,那么这一刀的起点和终点一定在蛋糕的边界