您的位置:首页 > 其它

<8/2>集训日记

2017-08-02 20:56 274 查看
今天看了有关欧拉函数,抽屉原理的内容。
首先欧拉函数phi(m)表示的是[1,m-1]中与m互质的数的个数,利用容斥原理可以给出其计算公式:
phi(m)=m*(1-1/p1)*(1-1/p2)*…*(1-1/pk)
其中p1,p2,…,pk为m的全部素因子。
以下是求数m的欧拉函数的代码:
代码1:此过程可求所有数的欧拉函数,适用于涉及多个数的欧拉函数的题
#include <cstdio>
#include <cstring>
#define LL long long
#define MAX 32768+1
using namespace std;
int eu[MAX];
void euler()//求出所有数的欧拉函数
{
       
inti, j;
       
for(i= 2; i < MAX; i++)
       
{
                
if(!eu[i])//用此判断i是不是素数
只需要将素数带入下一步
                
{
                        
for(j= i; j < MAX; j += i)//所有素因子中包含i的
                        
{
                                 
if(!eu[j])eu[j] = j;//如果在j之前没出现素因子,先乘它自己
                                 
eu[j]= eu[j]/i*(i-1);//相当于找到素因子
然后乘以原公式中的(1-1/pi)
                        
}
                
}
       
}
}
int main()
{
       
intt, n;
       
euler();
       
scanf("%d",&t);
       
while(t--)
       
{
                
scanf("%d",&n);
                
printf("%d\n",eu
);
       
}
       
return0;
}
这个方法相当于在素数i++的过程中,对多个数同时进行欧拉函数的计算,举例来说:
当i=2时,利用j=j+i这个循环,将所有能被2整除的数,也就是有2这个素因子的数进行了第一步计算(1-1/pi);
当i=3时,将有3这个素因子的数进行了乘(1-1/pi)的计算,其中,像eu[6]这个数,就带着之前在i=2时计算后的结果进行了第二次乘(1-1/pi)的计算;
当i=4时,以下的过程是没有意义的,因为i=2时已经计算完毕了,所以所有的合数i都不需要进行下去,于是用if(!eu[i])判断i是不是素数,只需要将素数带入下一步。
 
代码2:这个过程只求了输入的数n的欧拉函数
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
ll Euler(ll n)
{
       
llm=sqrt(n+0.5);
       
llans=n;//欧拉函数第一步:乘本身
       
for(inti=2;i<=m;i++)
       
{
                
if(n%i==0)//找到n的素因子i
                
{
                        
ans=ans/i*(i-1);//乘(1-1/i)
                
}
                
while(n%i==0)//不再考虑素因子i
                
n/=i;//把n中的i全除掉
       
}
       
if(n>1)//素因子大于m或者n就是素数
       
ans=ans/n*(n-1);
       
returnans;
}
int main()
{
       
lln;
       
while(cin>>n&&n)
       
{
                
llans=Euler(n);
                
cout<<ans<<endl;
       
}
       
return0;
}
这个方法就是最基本的计算,找到n的不重复素因子,按照公式n*(1-1/p1)*(1-1/p2)*…*(1-1/pk)计算。
 
单纯计算欧拉函数的题都比较容易,另外还有一种题型是结合欧拉函数和容斥原理的,如[HDOJ1695]
题意:给两个区间[a,b]和[c,d],求出有多少个数对(x,y)满足gcd(x,y)==
k,gcd为最大公约数。其中x属于区间[a,b]
,y属于区间[c,d],且
(x,y) 
和 (y,x)算一个数对。(题目说明a,c均可假设为1)
 
对题目进行分析,可以利用n = b / k,
m = d / k转化区间,将问题变为求区间[1,n]
和[1, m]
里面所有不重复的质数对(x,y),质数对的求解就可以利用欧拉函数和容斥原理了。
首先,可以假设n <= m,
当x,y同时x属于区间[1,n]时,所有不重复质数对(x,y)的数目就为n个数的欧拉函数之和;
当x属于区间[1,n]
而y属于区间[n+1,m]时,可以利用容斥原理枚举y,求区间[1,n]里面与该y互质的个数,最后累加。
 
所以在这个题中就需要用上面写到的求多个数的欧拉函数的代码,即代码1,然后将1到n所有的欧拉函数值求和,就是[1,n]中不重复的质数对。容斥原理部分不须变通。
这题还需要注意的一个小地方就是假设了n<=m,所以需要在一开始调整n,m顺序。
所用到的小代码之前都涉及了,不再粘过来了。
 

接下来是抽屉原理相关内容。
首先,抽屉原理在数学领域的定义是:将m个球放到n只抽屉中,一定有一只抽屉放进的球数不少于[(m-1)/n]+1个,其中[a]表示不大于a的最大整数,即向下取整。
但一般情况,普遍应用的定义是:将n+1个球放入n个抽屉,则有个抽屉中至少有2个球。
 
这里详细写一道抽屉原理的典型应用题:一个由n个数组成的数列,一定能找出若干个连续的数使它们之和能被n整除。[POJ
2356 Find AMultiple]
题目大意是:先给出一个数N,接着再给出N个数,要你从这N个数中选择若干个连续的数,使得其和是N的倍数。输出的第一行是选择元素的个数M,接着M行分别是选择的元素的值。答案若有多个输出任意一个即可。如果找不到这样的答案则输出0。
解题思路如下:
将n个数记为a[1],a[2],...a
.设置一个数组sum,sum[i]
= a[1] + a[2] + ...a[i]; 

1、如果存在一个k使得sum[k]%n==0,那么输出前k个数即可;
2、如果对于任意的k都有sum[k]
% n != 0,那么n个sum数组的元素除n后将会得到n个余数,这些余数一定大于等于1且小于等于n-1,由抽屉原理,这n个余数中一定可以找到两个相等的余数,即存在i,j,使得sum[i]%n=sum[j]%n(不妨设j>i),那么,(sum[j]-sum[i])%N=0,故sum[j]-sum[i]是N的倍数。此时,输出i
+ 1到j之间的数即可。
 
在POJ上AC的代码如下:
#include<iostream>
#include<cstdio>
using namespace std;
int sum[10005],a[10005];
int main()
{
       
intn;
       
intp=0;//标记
       
scanf("%d",&n);
       
for(inti=1;i<=n;i++)
       
{
                
scanf("%d",&a[i]);
                
sum[i]=sum[i-1]+a[i];
                
if(sum[i]%n==0)p=i;//直接找到
       
}
       
if(count!=0)//直接找到的情况输出a[1]到a[i]
       
{
                
printf("%d\n",p);
                
for(inti=1;i<=p;i++)
                
{
                        
printf("%d\n",a[i]);
                
}
                
return0;
       
}
       
for(inti=1;i<=n;i++)
       
{
     for(int j=i+1;j<=n;j++)
     {
       if((sum[j]-sum[i])%n==0)
       {
           printf("%d\n",j-i);//j-i即为要输出的元素的个数
           for(int k=i+1;k<=j;k++)//输出a[i+1]到a[j]
           printf("%d\n",a[k]);
       }
     }
   
}
}
看完了一个博客中有关容斥原理欧拉函数和抽屉原理的内容,感觉计算顺序、循环都与纯数学的方式有所差别,并且有些题中还需要考虑复杂度,可能会出现超时的情况。
 以上~
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: