zoukankan      html  css  js  c++  java
  • [题集]一些有趣的问题

    1.生成函数小技巧

    A

    不断求导可以配出$i^k$系数,每次多乘一个x,再求导,最后只会少了$a_0$

    B

    如果推出形如:$frac{p(x)}{q(x)}=A(x)$要求$A(x)$的递推式,其中p是n次项,q是m次项。
    则$A(x)*q(x)=p(x)$利用卷积,关注$[x^n]p(x)=[x^{n-m}]A(x)*[x^m]q(x)$即可得到$a_{n-m}$,然后下顺,即可依次得到$a_{n-m-1},a_{n-m-2}...$

    C

    $frac{P(x)}{Pi (x-a_i)^{k_i}}$化成部分分式:$sum frac{P_i(x)}{(x-a_i)^{k_i}}$
    直接通分,分子之和等于$P(x)$
    即:$P(x)=sum P_i(x) imes Pi_{j!=i}(x-a_j)^{k_j}$
    不妨考虑$modspace (x-a_i)^{k_i}$
    可以得到:$P(x)=P_i(x) imes Pi_{j!=i}(x-a_j)^{k_j}space modspace (x-a_i)^{k_i} $

    考虑进行分治处理:类似多点求值,进入左半边的时候,整体$modspace Pi_{j>mid}(x-a_j)^{k_j} $

    至于还需要:$Pi_{j!=i}(x-a_j)^{k_j}$还是类似分治

    再来一个多项式求逆即可得到:$Pi(x)$

    用处:可以继续化简$ frac{P_i(x)}{(x-a_i)^{k_i}}=sum_{j=1}^{k_i} frac{b_j}{(x-a_i)^{j}}$

    分子是一个常数,分母可以直接展开,获得这一项的O(1)公式。求通项的时候,分别对这$sum k_i$个的第$[x^n]$进行求和。O(k)求一项。胜过无脑快速递推的O(klogk)

    D

    $w^{i imes (n-i)}=w^{(C(n,2)-C(i,2)-C(n-i,2))}$然后除过去和n有关的。

     

     

    2.

    n*m的矩阵
    填数
    每行每列最大值必须恰好是Ci,Rj
    求方案数

    不妨对R,C排序,
    考虑如果是<=限制,(1,1)开始,当前在$(x,y)$.设R更小,可以直接走到(R+1,C),$ans imes=R_x^{m-y+1}$也就是后面的C的个数,C更小同理。


    可能无法保证最大值一定出现过。
    恰好出现最大值,考虑容斥。
    整体容斥很难办。按照==关系分段:$RRC<RCC<RC<RRCC$中间都是等于
    每一段的填法对应往下往右这个区域的方案数。

    黄色部分R=C,中间的黄色区域负责处理红色的填法

    显然每段独立。考虑对每段进行容斥。枚举哪些R哪些C不满足出现最大值,然后
    本段有nr个R,nc个C,之后有sr个R,sc个C,限制都是v

    $contribution=sum_{i=0}^{nr}sum_{j=0}^{nc} (-1)^{i+j}C(nr,i)(v-1)^{i(sc+nc)}C(nc,j)(v-1)^{j(sr+nr-i)}v^{(nr-i)(sc+nc-j)+(nc-j)(sr+nr-i)}$

    NTT优化:直接放到(i+j)的位置上,形如:$v^{ij}$要用上面的技巧优化

    最后每个位置加起来。

     

    3.

    构造题:

    N*M棋盘,1~N*M编号各出现一次

    曼哈顿距离不超过2的点对
    N<=1000
    度数确定4个角的点
    哈希函数:一个点到4个角的最短路以及最短路方案数
    然后唯一确定。。。直接还原

     

     

    4.

    四元环计数:[学习笔记]三元环

    还是暴力,O(msqrt(m)) 

     

     

    5.

    N个点,编号0~N-1
    如果popcount(i xor j) =K

    连边:
    i->j : weight:(ai+bj)
    j->i : weight(aj+bi)

    求root到各个点的最短路

    考虑建立虚点优化建图

    i到j xor为k,意味着把i的k位翻转

    f[i][j][k]当前为i,已经确定前j位,已经翻转了k位的点

    x->f[x][-1][0]->....->f[y][16][k]->y

    第一条和最后一条边权为ai和bj

    O(nlog^3)

    优化:

    1.中间的权值为0,dij取出第一个点,直接全部更新最短路

    2.当k>=17/2时候,连边:x->f[(1<<17)-x][-1][0]->....->f[y][16][17-k]->y

    即等价于翻回17-k次。

    这样k<=17/2,状态/=2

     

    6.

    走:
    (0,0,0)->(n,m,k)
    到(i,j,p)有代价:Ai+Bj+Cp
    求最小代价

    变成差分数组{ai,bi,ci},每一步都有一个代价。

    n+m+k步

    考虑放abcbcbabcbabcbacb

    每一步有一个带权的代价:val*后面的总步数

    翻转一下,1~n往上升。每个位置i的代价:val*i

    如果权值递减直接贪心
    有增加的一段,一定连续放在一起(交换法证明)
    并且是极长的连续一段。
    权值变成平均数,接着合并(还是交换法证明)

    然后变成递减的了,直接贪心

     

    7.

    程序自动分析·改:

    和NOI2015相同,但是没有数据组数,只有条件,有若干组数据,恰好每组数据最后一个会不合法,把它们分开。

    不能单点增量。

    倍增。

    每组长度为T,花费O(tlogt)的时间即可找到。

     

     

    技巧:check(l,r)不支持单点加入,只能离线后处理,划分序列
    倍增+二分
    每次失败,但是一定可以减少2^(k-1)的规模
    O(nlogn)

     

    扩展:

    给出一个有根二叉树
    m个限制,n个点,2-SAT限制的关系
    求每个点子树限制能否合法
    树剖,从每个叶子往上按照size倍增
    一个点成功了,整个子树都成功了,一个点失败了,整个到根的链都失败了
    这样倍增,还是花费O(szlogsz)的时间可以解决sz大小的点。

    必须按照sz倍增!否则按照深度倍增,可能突然出现很大的子树,导致进行常数极大的操作。

     

    8.

     

    N个点每个点度数2K(都是偶数且一样)的图,求一条哈密顿回路

    Hall定理推论:一个K正则二分图一定完美匹配
    跑欧拉回路定向,K入,K出

    然后拆入点出点2个
    找到完美匹配,直接模拟

     

    看到度数是偶数找路径或者给边定向什么的,都可以考虑找欧拉回路

    对于是入点出点的完美匹配,就是一条回路了!

     

     

     

     

    9.

    n个元素序列,每次删掉一个元素,左右放在一起,删完
    不能中途两个相邻的数相同
    求方案数

    n<=500

    删除问题,n<=500 考虑区间DP了

    定义f[l][r][vl][vr]l-1是vl,r+1是vr,删完l,r,的方案数

    其实没必要记录vl,vr,在考虑一个区间的时候,显然l-1,r+1都是不删除的。

    f[l][r]l-1,r+1都没有删,先删完l,r的方案数,

    枚举最后删除的转移,左右再乘上组合数分配先后顺序

    发现这样设计状态也确实符合转移

     

    扩展:

    随机删除,相邻相同停下来,求步数期望
    设gi为删了i个元素还没有停止的方案数
    ans=∑gi/(n的i次下降幂)
    求g,先做出刚才的区间DP O(n^3)
    直接在序列上分段,g[i][j]表示,前i个位置,i位置不删除,删除了j个元素的方案数。枚举最后删除的一段。乘上组合数分配先后。

    O(n^3)

     

    10.

    一张无向图,对于i<j<k,若i,j有边,i,k有边,那么j-k有边。

    反复进行这个过程。直到停止。

    有边的点对不能染相同颜色,共m种颜色,求方案数。

    如果图建好之后,不妨按照编号排序,每个点的染色方案就是:m-出边个数

    用并查集+set启发式合并合并边表

    一个点连出去的边:1.原来就往大连的,2.连到x的更小的y,y连到比x大的那些点。

    从小到大考虑,每个点x把所有连过来的点的边表合并在x上,并且用并查集表示这些边表在x这里。

    然后把x-x的边删除。之后直接从连过来的点的并查集处把这些边连过来。

    这样,2符合,并且不会边表里不会存在比x小的点(因为每次会删除x-x)

    边表合并,set启发式合并

     

    11.

    给定l,r,M,D,求最小自然数x,使得存在y使得,l<=Dx-My<=r
    y是整数,l,r,M,D是正整数,绝对值均<=1e18

    对于数据都<=1e9 BSGS分块
    对于数据<=1e18
    等价于找到最小的y,使得存在自然数x,使得,
    l<=Dx-My<=r
    -r<=My-Dx<=-l
    M=Dt+R
    -r<=(Dt+R)y-Dx<=-l
    -r<=Ry-D(-ty+x)<=-l

    找到k使得y+k>0

    即:Rk-r<=R(y+k)-D(-ty+x)<=Rk-l

    变成找到最小的y+k,使得存在(-ty+x)

    令y=y+k,-ty+x=y

    可以变成子问题递归。

    (类似gcd辗转相除)

     O(logn)

     

    法二

    二分+类欧几里得算法:

    看似是一个线性规划的感觉。

     

    二分x,看从x=0过来的区域内有无整点。

    O(log^2n)

     

    12.

    给定排列bi,维护数组ai,
    支持:ai整体+1,询问$sum [frac{ai}{bi}]$中括号表下取整
    总变化小于nlogn(调和级数
    线段树维护每个区间下一个存在一个点+1的距离。暴力
    每一次修改会到叶子,O(nlog^2)

     

    13.

     

    最小方差生成树
    求生成树:$sum(We-A)^2$最小值,A是平均数
    考虑枚举A的范围,交换排名,kruskal。过于暴力
    LCT处理每个边一定能加入的区间(保留最大时间生成树,端点是(val+mi)/2),正反处理两次

    然后模拟。

    存疑

     

    14.

    HDU6445

    给定竞赛图n<=300给没有定向的边定向,
    代价计算:for(a,b,c,d互不相等)
    if s(a,b)=s(b,c)=s(c,d)=s(d,a)++ans
    if s(a,b)!=s(b,c);s(b,c)!=s(c,d);s(c,d)!=s(d,a)--ans

    答案公式:

    所有有序4元组贡献上,

    无序4元组,存在一个出度为2的,不贡献,存在两个的,ans--

    枚举一个点,枚举其两个出点,再枚举另一个点,这个环至少是不贡献的,会被正反枚举共8次。

    发现对于两个度数为2的,恰好被扣除2次,符合倒扣ans

    然后就是“石头剪刀布”那个题了。

     

    竞赛图,考虑问题转化,变为度数的关系

     

    15.

    定义$gn(x)=Pi_{i<=n(i,n)==1}(x-w_n^i)$
    $w_n$是n次单位根。求$g1(x)……g2000(x)$

    反演

    $fn=Pi (x-w_n^i)=x^n-1$

    $fn=Pi_{d|n}g_d$

    $g_d=Pi_{d|n}f_d^{mu {frac{n}{d}}}$

    O(n^2logn)每次除法可以暴力O(n)进行

     

     

    16.

     

    求所有n<=300的无向连通图的1到2号点的最短路之和

     

    到所有点在所有连通图距离和,再除以(n-1)(显然对于1到2、1到3是等价的,可以直接除以n-1)

    边权为1,BFS分层图!

     

    考虑BFS树,f(i,j,k)前i层,最后一层j,深度k,方案数。枚举下一层点数,处理这层点自己内部连边和之前最后一层连边方案。

    k不必要,可以直接记到数值上。

     

    没有在这一层的,直接整体加上n-i

     

    f(i,j)i个点的分层图,最后一层j个点的贡献和。
    g(i,j)………………………………………………的方案数

     

    枚举下一层点数s,则连边方案乘上编号分配是:

    $c=C(i+s,s) imes (2^j-1)^s imes 2^{frac{s imes(s-1)}{2}}$

    转移方程:

    $g[i+s][j]+=g[i][j] imes c$

    $f[i+s][j]+=f[i][j] imes c+g[i][j] imes c imes (n-i-s)$最后剩下的统一加上(n-i-s)的路径。因为一定会有的。

    相当于假设所有没在这i个点之中的,都一定在下一层

     

    扩展1

    贡献变成最短路平方?

    $(s+1)^2=s^2+2*s+1$

    考虑维护没有在这i的点中的点所有方案里面的最短路距离和t[i][j]。

    发现对于每个点都是一样的,所以单独一个点其实所有方案中的最短路是:$frac{t[i][j]}{n-i}$

    $g[i+s][j]+=g[i][j] imes c$

    $t[i+s][j]+=frac{t[i][j]}{n-i} imes (n-s-i) imes c+g[i][j] imes c imes(n-i-s)$

    $h[i+s][j]+=h[i][j] imes c+2 imes frac{t[i][j]}{n-i} imes (n-s-i) imes c +g[i][j] imes c imes(n-i-s)$

     

    扩展2

    结论:定义图的直径为两两点对最短路的最大值,则补图和原图的直径的较小值<=3,(边权为1)

    考虑BFS树,两个最远点之间分层>=3时候,补图最大是3
    就是相邻分层图如果是有边,那么补图就是3

     

    17.

    (了解即可)

    二人博弈
    n个0/1串,0号可以删除一个串的0开始的后缀,1类似。
    n,m<=100
    最后不能删者输

     

    不公平博弈但是面对局面越来越差:超现实博弈?

     

    神仙结论?
    每个串权值:AAAABABB=3+0.100 1
    看做二进制小数,看总和谁的更大
    总和一定,后手赢

     

    证明:每一步权值都会下降
    每一次操作要么减少自己的权值,要么增大对方的权值
    所以权值多的一方总能赢。

     

     

     

     

     

    扩展?

    AAB(BABAABAB)BBAB括号内重复无穷次,求解。每个串至多一个括号
    小数点前无穷是inf级别,还有常数
    小数点之后无穷等比数列变成常数,最后是1/inf

     

     

    18.

    定义$gn(x)=Pi_{i<=n(i,n)==1}(x-w_n^i)$
    $w_n$是n次单位根。求$g1(x)……g2000(x)$

    反演

    $fn=Pi (x-w_n^i)=x^n-1$

    $fn=Pi_{d|n}g_d$

    $g_d=Pi_{d|n}f_d^{mu {frac{n}{d}}}$

    O(n^2logn)每次除法可以暴力O(n)进行

     

    19.

    支持:
    后面插入一个数,区间求xor和,整体xor,整体排序

    一个前缀是排好序的,后面插入的单独记录

    前缀用trie维护,后面插入还未排序的用数组记录。

    区间xor和,就是找两个第k大进行前缀差分。前缀在trie树上二分即可,后面的用数组直接搞。

    整体xor就是整体mark。再求区间xor时候,如果元素个数是奇数,xor上mark

    插入一个数,xor上mark再插入进去。

    sort?

    后面合并到trie树上,但是有mark标记,使得可能顺序还有变化,

    trie树整体标记mark,pushdown时左右儿子交换即可。

    然后mark置零

     

    0/1trie上可以很方便对二进制数排序,并且整体xor上,就是交换儿子。

     

    20.

    n(n<=5)个元素的序列{xn},ai<=xi<=bi,且LIS=k的方案数

    bi-ai<=100


    法一:爆搜+Dp?
    法二:

    k=1,k=5好算,APIO划艇

    k=2或者k=4 DP套DP f[i][j][k]填了前i个,LIS栈里面第一个是j第二个是k方案数

    k=3直接减掉

     

    21.

    CF809D

    长度为n的序列{xi},n<=3e5,范围在(li,ri)之间,求LIS最长是多长
    g(i,l)表示前i个数,LIS长度为l,最后一个数最小是多少(就是那个单调栈)
    g(i,l)=min(g(i-1,l),xi (if exist j g(j,l-1)<x))
    关于l是递增的。
    虽然不知道xi是多少,

    但是可以直接用(li,ri)进行计算!最后一定存在一种方法还原xi

    刚好可以把一个g(i-1,l-1)+1->g(i,l)

    整个区间往上平移再往右平移,再再最下面插入一个点。

    实现时候,用平衡树,直接区间+1,某位置插入一个点

    最后平衡树点数即为答案

     

    #include<bits/stdc++.h>
    #define reg register int
    #define il inline
    #define fi first
    #define se second
    #define mk(a,b) make_pair(a,b)
    #define numb (ch^'0')
    #define pb push_back
    #define solid const auto &
    #define enter cout<<endl
    #define pii pair<int,int>
    using namespace std;
    typedef long long ll;
    template<class T>il void rd(T &x){
        char ch;x=0;bool fl=false;
        while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
        for(x=numb;isdigit(ch=getchar());x=x*10+numb);
        (fl==true)&&(x=-x);
    }
    template<class T>il void output(T x){if(x/10)output(x/10);putchar(x%10+'0');}
    template<class T>il void ot(T x){if(x<0) putchar('-'),x=-x;output(x);putchar(' ');}
    template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar('
    ');}
    
    namespace Miracle{
    const int N=3e5+5;
    int n,l[N],r[N];
    int tot;
    struct node{
        int ls,rs;
        int ad;
        int val;
        int prio;
    }t[2*N];
    int nc(int v){
        ++tot;t[tot].val=v;t[tot].prio=rand();
        t[tot].ad=t[tot].ls=t[tot].rs=0;
        // cout<<" nc "<<tot<<" : "<<v<<endl;
        return tot;
    }
    void pushdown(int x){
        if(x&&t[x].ad){
            t[t[x].ls].ad+=t[x].ad;
            t[t[x].rs].ad+=t[x].ad;
            t[t[x].ls].val+=t[x].ad;
            t[t[x].rs].val+=t[x].ad;
            t[x].ad=0;
        }
    }
    void split(int now,int &x,int &y,int k){//<=k
        if(!now){
            x=0;y=0;return;
        }
        pushdown(now);
        if(t[now].val<=k){
            x=now;split(t[now].rs,t[x].rs,y,k);
        }else{
            y=now;split(t[now].ls,x,t[y].ls,k);
        }
    }
    int dele(int x){
        pushdown(x);
        int rt=x;
        if(!t[x].ls) {
            // cout<<" delert "<<x<<" "<<t[x].val<<endl;
            return t[x].rs;
        }
        int y=0;
        while(t[x].ls){
            // cout<<" ls "<<x<<" las "<<y<<endl;
            pushdown(x);
            y=x;
            x=t[x].ls;
        }
        // cout<<" dele "<<x<<" "<<t[x].val<<" "<<t[x].ls<<" "<<t[x].rs<<endl;
        t[y].ls=t[x].rs;return rt;
    }
    int merge(int x,int y){
        if(!x||!y) return x+y;
        pushdown(x);pushdown(y);
        if(t[x].prio<t[y].prio){
            t[x].rs=merge(t[x].rs,y);
            return x;
        }else{
            t[y].ls=merge(x,t[y].ls);
            return y;
        }
    }
    int ans=0;
    void fin(int x){
        if(!x) return ;
        pushdown(x);
        ++ans;
        fin(t[x].ls);
        // cout<<" x "<<x<<" : "<<t[x].val<<endl;
        fin(t[x].rs);
    }
    int main(){
        srand(19260817);
        rd(n);
        for(reg i=1;i<=n;++i){
            rd(l[i]);rd(r[i]);
        }
        int rt=0;
        for(reg i=1;i<=n;++i){
            int x,y,p,q;
            split(rt,x,y,l[i]-1);
            split(y,p,q,r[i]-1);
            t[p].ad++;
            t[p].val++;
            // if(i==n) {
            //     // cout<<" qqqq "<<endl;
            //     fin(q);
            // }
            q=dele(q);
            // if(i==n) {
            //     // cout<<" qqqq "<<endl;
            //     fin(q);
            // }
            rt=merge(merge(merge(x,nc(l[i])),p),q);
            // cout<<"finfifn "<<i<<"------------------------"<<endl;
            // fin(rt);
        }
        ans=0;
        fin(rt);
        ot(ans);
        return 0;
    }
    
    }
    signed main(){
        Miracle::main();
        return 0;
    }
    
    /*
       Author: *Miracle*
    */
    View Code

     22.

    构造长度为2n的序列,使得所有前缀写出的二进制数mod 2n恰好是0~2n-1

    2n个点的图,x->2x和2x+1连边,求哈密顿路径
    分成x,x+n一个2个点团,(自环)(0,3)<-->(1,4)<-->(2,5)(自环)
    求欧拉回路,相邻团的连边方案唯一。直接还原

     

    23.

     

    小公式:
    给定n,$sum_{(i,n)==1}gcd(i-1,n)=phi(n)*sigma_0(n)$

     

    用置换群理论可以证明。
    设集合S={x|0<=x<n},置换:任意$(gamma ,n)=1$定义$g_{gamma}(x)=gamma * x$

    该置换有元置换和置换传递性,可以构成置换群
    考虑相同的x1,x2,即是否存在$gamma$使得$gamma*x_1=x_2 mod space n$

    必然有gcd(x1,n)==gcd(x2,n),那么本质不同的元素(轨道数量)一共有$sigma_0(n)$个

    再枚举每个置换下不动点的个数:$gamma imes x=xspace mod space n$的x的解的个数是:$gcd(gamma-1,n)$

    也就是:$sigma_0(n)=frac{sum[gcd(i,n)==1] imes gcd(i-1,n)}{phi(n)}$

    把分母乘过去就可以证明了。

     

     

    24.

    nm的0/1矩阵,每行删除一个,相邻两行删除横坐标距离不超过k
    删完之后成为n(m-1)矩阵,求删完之后的矩阵本质不同方案数

    n,m,k<=300

    直接记录f(i,j)是不行的,显然会算重复

    具体的,每行连续的1连续的0删除几个都是一样的。

    所以不妨把连续的一起考虑化成若干段

    考虑在字典序最小的位置统计!

    也就是,能在左端点删就在左端点删。

    但是k的限制,有的时候必须删中间一个。如图中的红色的圆形

    这样,为了字典序最小,一定是连续每k个删除一次,直到删除到一个左端点。

    这个时候就又变成叉号了。

    所以f[i][j],g[i][j]O(n^3)DP即可

    25.

    EC Final 2018

    长度为n和m的两个序列,每个位置3种可能,+1,-1,?

    把?替换成-1或者+1

    从(0,0)开始拿1元走,如果>=2随机上面或者下面走一步,如果是1,走+1的那一个序列,都是+1随机。如果钱==0结束

    求多少种填法方案保证到(n,m)才结束

    n,m<=5000

    有点任意性的感觉,有一个结论:

    如果存在n,m的两个位置x,y使得x-1的前缀和加上y-1的前缀和为0,并且x,y都是-1,那么不能保证

    证明考虑任意性。

    然后DP:即两个序列前缀最小值之和不能<=-2

    两个序列相对独立了

    f[i][j][k],前i个,当前最大值是j,历史最大值是k

    貌似不能化简状态了

    发现0的前缀和为0

    考虑反过来Dp~!相对设法

    f[i][j]从后往前到第i个,当前值距离历史最小值为j方案数

    最后f[0][j]的j就是真实最小值了。

  • 相关阅读:
    uml 类图
    Java IO流
    Spring 创建Bean的 三种方式
    linux+jmeter+python基础+抓包拦截
    接口测试
    HDU 1159 Common Subsequence(POJ 1458)
    HDU 1160 FatMouse's Speed
    HDU 4540 威威猫系列故事——打地鼠
    HDU 1087 Super Jumping! Jumping! Jumping!
    HDU 1176 免费馅饼
  • 原文地址:https://www.cnblogs.com/Miracevin/p/10809966.html
Copyright © 2011-2022 走看看