概述
1. 错误:
10.30,模拟考试第二题,对于题目中可走的边的定义:u-v可走当且仅当存在一条从v出发的路其路程小于从u出发的到终点的所有的路,题目要求求满足这样的条件的路(起点,终点固定)的方案数,理解成了求最短路的条数,惨死……
2.错误:
10.30,模拟考试第三题,在判断列上面是否已经不满足条件的时候,在当前列上的最后一堆数的判断过程中,下意识地把程序代入到自己设想中的情况里,以为当前的最后一堆数也是标准要求的最后一堆数,(即,把自己当前所想的特殊情况混淆到程序中,忽略了现实与想象的严格区别)。
3.技巧 图论
对于存在一个环的图(多个环的没有试过),随机取出一条环上的边的方法:参照最小生成树中克鲁斯卡尔算法的思想,每次用最小的代价将两个已经生成好的小的最小生成树连接起来,那么我们在读入这个图的时候,就可以每次取出这一条边的u和v,如果发现他们的老爸不相同,那么说明他们原本并不连通,正常连接即可,如果发现他们的老爸相同,那么说明他们已经连通,则不连这一条边,标记出这一条边即可。
4.技巧 图论
对于一个图,多次询问任意两个点之间的距离,如果其点数与边数都比较小,比如说都在1000-2000之内,那么直接暴力处理从每个点出发到每个点的最短路就OK。
如果数据规模较大,比如说达到了100000,但是给出的图是一棵树,那么使用LCA求两点间的距离即可(LCA偏好使用树链剖分)。
如果数据规模与特征与上面几乎一样,但是多了一条边,也就是说多了一个环,那么(别以为做一遍最小生成树就OK了,行不通)对于两个点,我们需要分类讨论,那就是在遇到了我们所找到的那个环的时候,看看是顺时针走还是逆时针走,这样想来我们需要DFS去找环,还有一些其他的麻烦的东西,实在麻烦,一个简单的实现方法就是,我们采用3里面提到的技巧,在建图的时候,把环上的一条边找到,记录下他的u,v,value,并且断掉他,那么我们就生成了一个去掉任意一条环上的边的树,在接受询问x,y的距离的时候,我们设它们的最近公共祖先为fa,则一个候选答案就是dis.u+dis.v-2*dis.fa,也就是正常的LCA求距离,相当于我们求了环上的其中一种方向,我们记这样的一个过程为f.x.y,那么对于另外一种方向的距离,就是f.x.u+f.y.v+value或者f.x.v+f.y.u+value,(有可能有交叉,你并不知道它们的顺序是什么),最后取三种答案的最小值就可以了。
5.技巧 数论
欧拉定理,(a^phi(p))%p=1,当p为质数的时候phi(p)=p-1;
应用:
(1) 求乘法逆元,当我们需要求(x/a)%p的时候,是不能直接取模的,这就需要用到a的乘法逆元,也叫作a对于p的数论倒数,我们记为y,y满足(x*y)%p=(x/a)%p,那么y应该怎么求呢?结论是,若(a*y)%p=1,那么y就是a关于p的乘法逆元(a需要与p互质),这里我们考虑p是质数的情况,根据欧拉定理我们已知(a^phi(p))%p=1,以为p为质数,所以(a^(p-1))%p=1,所以y可以等于a^(p-2),我们的出结论,当p为质数且a,p互质时,a关于p的乘法逆元可以为a^(p-2)。
(2)质数检测,根据欧拉定理,我们知道,若p为质数,则(a^(p-1))%p=1,这个命题显然不是充要的,但是要满足这个命题的非质数的情况还是几率不太大的,所以我们可以多使用几个数来检测,多次筛选,如果我们这些数的测试都过了的话,才概率地确定它是一个质数。
(3)对快速幂的取模,如果我们遇到形如2^(99999^(99999^(99999^(99999^99999))))%p一类的问题,我相信你不敢大胆地直接把指数%p的,那么,根据欧拉定理,(a^(phi(p)))%p==1,我们可以把phi(p)作为周期,因为每到phi(p),Power下来就变成了1,所以我们只需要将指数对phi(p)取余,把取余出来的数作为指数就可以了,由于a^0=1,所以当指数为phi(p)的倍数的时候,取余下来正好为0,得到结果1。
6.技巧 数论
欧拉函数,phi(p)表示小于p的数中与p互质的数,注意1也算。
性质:
(1)显然,若p为质数,则phi(p)==p-1;
(2)若a,b互质,则phi(a*b)==phi(a)*phi(b);
(3)若p为质数,k为正整数,则phi(p^k)==(p-1)*p^(k-1),为什么满足这个式子呢?这是因为求欧拉函数的公式为phi(n)==n*((p1-1)/p1)*((p2-1)/p2)*((p3-1)/p3)……其中pi为n的质因数且pi互不相同,有了这样一个公式,我们可以理解,因为phi(p)=p-1,那么p*p并不改变它的质因子种数,只是扩大了前面的n而已。
求法:
(1)若我们需要求1-n的所有欧拉函数,那么我们可以结合欧拉筛,代码如下:
void Get()
{
bool visit[n]={0};
int prime[maxn]={0},phi[n]={0};
for(int i=2;i<=n;i++)
{
if(!visit[i]){prime[++prime[0]]=i;phi[i]=i-1;}
for(int j=prime[0];i*prime[j]<=maxn;j++)
{
visit[i*prime[j]]=1;
if(i%prime[j]==0)
{
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
phi[i*prime[j]]=phi[i]*(prime[j]-1);
}
}
}
这个算法的时间复杂度是O(n)的,已经是最优复杂度了。
(2)当我们只需要求一个数的欧拉函数的时候,我们就可以采用性质里面提到的公式,利用根号n(实际上不到)的时间对所求数分解质因数,然后直接计算就可以了,代码如下:
int Get()
{
int ans=n;
for(int i=2;i*i<=n;i++)
{
if(n%i==0)
{
ans=ans-ans/i;
while(n%i==0)n/=i;
}
}
if(n>1)ans=ans-ans/n;
return ans;
}
最后
以上就是暴躁舞蹈为你收集整理的技巧与错误的全部内容,希望文章能够帮你解决技巧与错误所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复