跳蚤
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 9225 | Accepted: 2762 |
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
首先我们假设卡片上的标号分别是a1,a2,.....an,M 跳蚤对应号的 次数分别为x1,x2...xn,跳M个单位长度的次数时xn+1,那么根据条件可以列出方程a1x1+a2x2+...Mxn+1 = 1
,要使得这个方程有解即(a1,a2,...M)=1 就是说这n+1个数的公因子是1,至此由于M是最大的数,因此对M分解然后排除公因子不是1的情况就行了。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <stack> 5 #include <queue> 6 #include <map> 7 #include <algorithm> 8 #include <vector> 9 #include <cmath> 10 11 using namespace std; 12 13 const int maxn = 1000005; 14 15 typedef long long LL; 16 17 int fac[1005]; 18 int t; 19 20 void divide(int m) 21 { 22 int i; 23 t = 0; 24 int k = (int)sqrt(m); 25 for(int i=2;i<=k;i++){ 26 if(m%i == 0){ 27 t++; 28 fac[t] = i; 29 while(m%i == 0) 30 m /= i; 31 } 32 } 33 if(m != 1){ 34 t++; 35 fac[t] = m; 36 } 37 } 38 LL quick_multi(LL a,LL b) 39 { 40 LL ans = 1; 41 while(b){ 42 ans *= a; 43 b--; 44 } 45 return ans; 46 } 47 48 LL ans,temp; 49 int a[100],m,n; 50 51 void dfs(int b,int ct,int c) //有c个公因子 52 { 53 int i,x; 54 if(ct == c){ 55 x = m; 56 for(i=1;i<=c;i++){ 57 x /= a[i]; 58 } 59 temp += quick_multi(x,n); 60 return ; 61 } 62 for(i = b+1;i<=t;i++){ 63 a[ct+1] = fac[i]; 64 dfs(i,ct+1,c); 65 } 66 } 67 int main() 68 { 69 int i; 70 while(scanf("%d%d",&n,&m)!=EOF){ 71 ans = t = 0; 72 divide(m); 73 for(int i=1;i<=t;i++){ 74 temp = 0; 75 dfs(0,0,i); 76 if(i&1){ 77 ans += temp; 78 } 79 else 80 ans -= temp; 81 } 82 ans = quick_multi(m,n) - ans; 83 printf("%lld ",ans); 84 } 85 86 return 0; 87 }