跳蚤
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 8298 | Accepted: 2434 |
Description
Z城市居住着很多只跳蚤。在Z城市周六生活频道有一个娱乐节目。一只跳蚤将被请上一个高空钢丝的正中央。钢丝很长,可以看作是无限长。节目主持人会给该跳蚤发一张卡片。卡片上写有N+1个自然数。其中最后一个是M,而前N个数都不超过M,卡片上允许有相同的数字。跳蚤每次可以从卡片上任意选择一个自然数S,然后向左,或向右跳S个单位长度。而他最终的任务是跳到距离他左边一个单位长度的地方,并捡起位于那里的礼物。
比如当N=2,M=18时,持有卡片(10, 15, 18)的跳蚤,就可以完成任务:他可以先向左跳10个单位长度,然后再连向左跳3次,每次15个单位长度,最后再向右连跳3次,每次18个单位长度。而持有卡片(12, 15, 18)的跳蚤,则怎么也不可能跳到距他左边一个单位长度的地方。
当确定N和M后,显然一共有M^N张不同的卡片。现在的问题是,在这所有的卡片中,有多少张可以完成任务。
比如当N=2,M=18时,持有卡片(10, 15, 18)的跳蚤,就可以完成任务:他可以先向左跳10个单位长度,然后再连向左跳3次,每次15个单位长度,最后再向右连跳3次,每次18个单位长度。而持有卡片(12, 15, 18)的跳蚤,则怎么也不可能跳到距他左边一个单位长度的地方。
当确定N和M后,显然一共有M^N张不同的卡片。现在的问题是,在这所有的卡片中,有多少张可以完成任务。
Input
两个整数N和M(N <= 15 , M <= 100000000)。
Output
可以完成任务的卡片数。
Sample Input
2 4
Sample Output
12
Hint
这12张卡片分别是:
(1, 1, 4), (1, 2, 4), (1, 3, 4), (1, 4, 4), (2, 1, 4), (2, 3, 4),
(3, 1, 4), (3, 2, 4), (3, 3, 4), (3, 4, 4), (4, 1, 4), (4, 3, 4)
(1, 1, 4), (1, 2, 4), (1, 3, 4), (1, 4, 4), (2, 1, 4), (2, 3, 4),
(3, 1, 4), (3, 2, 4), (3, 3, 4), (3, 4, 4), (4, 1, 4), (4, 3, 4)
Source
HNOI 2001
题目:求a[1]*x1+a[2]*x2+...a[n]*xn+m*xn+1=1,有解时,a[1],a[2]...a[n]的不同排列个数
抽象:求gcd(a1,a2,...an,m)=1的排列数
思路:不妨定义原问题为f(m),则当gcd(a1,a2,...an,m)=d时,a[1]...a[n]的排列数,而此时它等价于gcd(a[1]/d,a[2]/d....a[n]/d,m/d)=1的排列数即为f(m/d),由莫比乌斯反演公式有:
其中u(d)表示d的莫比乌斯函数值,而莫比乌斯函数为:
1 d=1
u(d)= (-1)^r d=p1*p2*p3....pr(均为互不相同的素数)
0 其他情况
所以该题的反演过程是从n=1开始,然后接下来只计算为互不相同的素数相乘得到的d的过程。
具体实现方法可以由DFS实现。
题目:求a[1]*x1+a[2]*x2+...a[n]*xn+m*xn+1=1,有解时,a[1],a[2]...a[n]的不同排列个数
抽象:求gcd(a1,a2,...an,m)=1的排列数
思路:不妨定义原问题为f(m),则当gcd(a1,a2,...an,m)=d时,a[1]...a[n]的排列数,而此时它等价于gcd(a[1]/d,a[2]/d....a[n]/d,m/d)=1的排列数即为f(m/d),由莫比乌斯反演公式有:
∑u(d)∑f(m/d)=f(m) d|m d|m对于一个函数f(n),记它的和函数为
∑f(d) d|m则反演有:
∑u(d)∑f(m/d)=f(m) d|m d|m
其中u(d)表示d的莫比乌斯函数值,而莫比乌斯函数为:
1 d=1
u(d)= (-1)^r d=p1*p2*p3....pr(均为互不相同的素数)
0 其他情况
所以该题的反演过程是从n=1开始,然后接下来只计算为互不相同的素数相乘得到的d的过程。
具体实现方法可以由DFS实现。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
long long ans;
long long n,m;
int cnt;
long long power(long long a,long long p)
{
long long res=1;
while(p)
{
if(p&1)
res*=a;
a*=a;
p/=2;
}
return res;
}
long long p[100005];
void dfs(int s,long long pri,int flag)
{
// cout<<s<<" "<<pri<<" "<<flag<<endl;
ans+=flag*power(m/pri,n);
for(int i=s+1;i<cnt;i++)
{
dfs(i,pri*p[i],-flag);
}
}
int main()
{
while(cin>>n>>m)
{
cnt=0;
long long temp=m;
for(long long i=2;i*i<=temp;i++)
{
if(temp%i==0)
{
p[cnt++]=i;
while(temp%i==0)
temp/=i;
}
}
if(temp>1)
p[cnt++]=temp;
ans=power(m,n);
for(int i=0;i<cnt;i++)
dfs(i,p[i],-1);
cout<<ans<<endl;
}
return 0;
}