zoukankan      html  css  js  c++  java
  • 寒假集训补完

    数论

    poj3708:根据题意就是把m的每一位按照b的置换(特别的第一位是按照a的置换)转变成k,对每一位考虑,就可以得出一个模方程,整个就是解模方程组。就是列方程有点复杂,刚开始转成进制有点复杂,要写高精度除单精度。

    hdu1695:求1<=x<=m,1<=y<=n内gcd(x,y)=k的数对,并且(x,y)(y,x)算一种。设F(n)表示k|gcd(x,y)的对数,f(n)表示gcd(x,y)=k的对数,那么发现F和f满足莫比乌斯反演的第二种形式,所以f(k)=Σμ(d/k)F(d),因为x和y都是k的整数倍,所以问题不妨变成1<=x<=[m/k]=m',1<=y<=[n/k]=n',gcd(x,y)=1的个数。所以ans=f(1)=Σμ(i)[m'/i][n'/i],对后面这个分组求和就行。还有另外一种推法,就是根据Σμ(d)=[n=1],这个问题里的gcd(i,j)=k,把m,n除以k后问题就成了[gcd(i,j)=1],直接用Σμ(d)替换掉,直接得出最终式子。

    bzoj2154:类似的反演操作,难点是遇到一个式子的求解F(x,y)=Σ(1<=i<=x,1<=j<=y,gcd(i,j)=1)i*j,设g(d)表示gcd(i,j)=d时候该式子的答案,那么g(d)=Σ(d|n)μ(n/d)G(n),我们需要的是g(1)=Σμ(i)G(i),根据g的含义,G(d)为gcd(i,j)|d时候的总和,所以G(d)=Σ(1<=i<=x/d,1<=j<=y/d)i*j,这个就可以直接列出式子了。此题需要一个分块套一个分块,所以时间是O(n)的。注意最后输出结果的时候ans=(ans+mod)%mod。

    hdu5226:求杨辉三角的一个矩阵的和,发现这个矩阵的每一列的和可以写成两个C的差,所以方法就是枚举列,将这些C加起来,于是问题的关键就变成了组合数取模,这里的p是输入的素数,n,m<=1e5,容易想到直接预处理阶乘的逆元,但是如果p比较小,i如果正好是p的倍数,那么i!就没有逆元了,所以要用lucas定理把所有数都变成<p的,预处理的逆元只需要做到min(b+1,p-1)。

    poj2888:对一串循环的珠子染色,但是要求有k对颜色的珠子不能相邻。(n<=1e9,m<=10,k<=1e5)。如果没有限制那就是个polya定理,这里有限制,那也就是说对于一个置换的不动点,不能用乘法原理直接求,需要递推求解。对于循环置换,一共有gcd(n,L)个轮换,每个轮换颜色必须相同,所以问题就变成了对1~gcd(n,L)按照限制染色(头尾颜色要相同),那么这个方案数就是L置换下不动点的个数。易得方程f[i][j]=Σf[i-1][k]*a[k][j],那么这个就容易让人想到矩阵优化,对颜色的01矩阵a自乘k次,矩阵的对角线的和也就是表示长度为k时候总方案数(走k步自己走回自己)。还有一个优化,就是gcd(n,L)的种类不会很多,只要枚举到sqrt(n)即可,那么每种种类出现了多少次呢?就是对应的欧拉函数。时间复杂度是O(sqrt(n)*log(n)*m^3)。哦对了,最后根据Burnside引理,要除以n,所以要求出n对模数的逆元。因为这里gcd(n,mod)=1,所以必存在逆元。这题有个坑点,就是注意欧拉函数的写法,因为素数筛到的是sqrt(n),所以还有可能有个大于sqrt(n)的素数,最后要注意乘上去。

    codeforces 258D:给n个数,m个操作,每次操作(i,j)有50%概率交换i,j位置上的数,问最后逆序对数的期望。设f[i][j]表示第i位比第j位大的概率,那么对于每次修改(x,y),很明显f[x][y]=f[y][x]=(f[x][y]+f[y][x])/2,对于其它位置i,f[i][x]=f[i][y]=0.5*f[i][x]+0.5*f[i][y],最后答案根据f[i][j]扫一遍就行了。

    codeforces 235D:第一步先要转换一下题目要求的东西,题目要求的是一个连通块的权值,我们发现如果删除一个点v,那么就相当于给ans加上删除v前与v处于同一个连通块的点的个数。我们可以枚举每一个有序点对(u,v),表示删除u之前u和v是连通的概率,那么ans就是所有点对的概率和。题中的图是一个树上加一条边,不妨先考虑树的情况。在一棵树上,u到v的路径只有一条,设路径上的点数为t,那么很明显(u,v)的概率是1/t,考虑删点顺序的全排列t!(不在路上的点是自由的,不考虑),那么唯一满足的情况就是第一位必须放u,其他放后面,也就是(t-1)!/t!=1/t。现在在树上加了一条边,存在了一个长度为L的固定环,两点之间的路径就可能有了两条,设一条路径上的点数为l1,一条路径上的点数为l2,那么从u->v可能经过的所有点数就是(l1+l2+L-2)/2,考虑两种情况,一种是第一条路径自由,概率为1/l2,一种是第二条路径自由,概率为1/l1,但是有公共的情况要减掉,就是u在第一位,其它点都在其后面,2/(l1+l2+L-2),所以总的概率贡献就是1/l1+1/l2-2/(l1+l2+L-2)。现在就是如何操作的问题了,首先对于那个环的长度L,可以一开始直接拓扑排序,剩余的点数就是环的长度L。接下来如果固定一个点为树根,那么任意两个点对之间的查询就可能涉及到lca,变得麻烦,有个很好的技巧就是以每个点i为根dfs,算出(i,x)的答案。每次dfs到某点k的时候,判断当前到k的路径是不是第一次,如果是,直接加上单条路的贡献,并把当前的长度计入d1[k],如果不是,也就是说有d[k]和d1[k]两条了,因为之前的1/d1[k]已经加过了,所以这里只要加1/d[k]-2/(d[k]+d1[k]+L-2)。

    数据结构

    hdu4836:若没有root操作,那么就先dfs序,然后就变成了单点修改区间查询,可以用树状数组完成。假如以1为根建树,题目要求的根为root,那么若询问不在root->1上,没影响,如果询问在root->1上,那么ans=总的和-该询问儿子节点所在子树的权值和。

    bzoj1195:很容易想到建一个AC自动机。然后在AC自动机上跑状压dp,dp[i][s]表示到了自动机的节点i,字符串包含关系为s的最短步长,可以在建立next[]的时候顺便求出每个点的danger[i]表示到了i点,说明包含了字符串的情况,那么就可以变成了从root出发,bfs,直到当前状态包含了所有字符串(按照字典序遍历)。有几点要注意:建立vis[u][s]数组表示状态(u,s)是否之前到过,如果到过,则说明可以以更小的步长到达状态(u,s),当前状态不需要扩展下去;输出方案的时候不能直接把输出字符串情况加入到队列的节点中,这样会TLE、MLE;考虑记下第一次到达状态(u,s)的fromu和froms以及fromid(就是边上的字符),也就是一直保持步长最小记录前缀,因为bfs就是按照步长最小记录下来的;因为空间要求32MB,所以要用short int。

    zerone:对于删去一些字符串的问题,我们可以转变成保留一些字符串,那么可以对所给字符串建一个trie,发现从底向上可以算出每个点的sg值,从而判断root的sg值。对于每次新进来的字符串,我们只需要修改该字符串所在链上的点的sg值,所以时间效率是O(nLen),但空间复杂度很高,也是O(nLen)的,注意到字符种类只有0、1,每个字符串长度只有64,所以将Trie的一条链缩链,用1<<64的二进制表示该节点下面的边。

    图论

  • 相关阅读:
    JQuery Ajax调用asp.net后台方法
    擦亮自己的眼睛去看SQLServer之简单Insert
    擦亮自己的眼睛去看SQLServer之简单Select
    SQL Server CONVERT() 函数
    给reporting services加个条件型的格式 (轉)
    优化SQL语句:in 和not in的替代方案
    技术不如你,但老板就是赏识他,为什么?
    LINQ to SQL活学活用(1):这要打破旧观念(轉)
    [续] MATLAB 混合编程——下篇:调用其它编程语言
    [精] MATLAB 混合编程——上篇:被其它编程语言调用
  • 原文地址:https://www.cnblogs.com/wmrv587/p/6337168.html
Copyright © 2011-2022 走看看