您的位置:首页 > 其它

poj 1091 跳蚤

2013-09-04 16:02 246 查看
终于知道容斥定理是个啥玩意了,真神奇。

题意略,其实幻化为表达式就是a1*num1+a2*num2+a3*num3+......an*numn = 1;本人没学过数论,但是一眼就看出这个表达式的意思就是说这n个数的gcd为1,结果baidu了一下,竟然真中枪了,原话是这样的(n个数的最大公约数规定为这n个数线性和的最小自然数,所以此题就是要求最大公约数为1的数列的个数);其实这题数据很水,明显会用到高精度的,但是用__int64就能低空水过掉(水是一种风格),算gcd为1的数列种数肯定不好算,然后换个方向来进行计思考,可以先算出总数目m^n然后减去gcd不为1的,gcd不为1的情况有很多重复的,这时又得用到组合数学中的容斥定理(很经典的,用处也很多,不妨学一下。),这组合数学不懂真心完全理解不了,相信看完容斥定理的人看我代码也就懂了。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 101;
int cou;

typedef struct {
int i,flag;
}Node;

Node arr
;

bool cmp(Node a,Node b)
{
return a.i<b.i;
}

__int64 mypow(__int64 a,__int64 b)
{
__int64 sum = 1;
while(a--)
{
sum *= b;
}
return sum;
}

void getdiv(__int64 m)
{
int n = 1;
int i;
for(i=2;i*i<m;++i)
if(m%i==0)
{
arr[n++].i = i;
arr[n++].i = m/i;
}
if(i*i==m)
{
arr[n++].i = i;
}
arr[n++].i = m;
sort(arr+1,arr+n,cmp);
cou = n;
for(int i=1;i<cou;++i)
{
bool flag = true;
int k = 0;
for(int j=1;j<i;++j)
if(arr[j].flag==1&&arr[i].i%arr[j].i==0)
{
++k;
flag = false;
if(arr[i].i%(arr[j].i*arr[j].i)==0)
{
k = 0;
break;
}
}
if(!flag)
arr[i].flag = k;
else
arr[i].flag = 1;
}

}

int main(void)
{
int n,m;
while(scanf("%d %d",&n,&m)!=EOF)
{
__int64 ans = mypow(n,m);
getdiv(m);
for(int i=1;i<cou;++i)
{
if(arr[i].flag==0)
;
else if(arr[i].flag%2)
{
ans -= mypow(n,m/arr[i].i);
}
else
{
ans += mypow(n,m/arr[i].i);
}
}
cout<<ans<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: