跳蚤
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 7929 | Accepted: 2309 |
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)
好吧,给我的教训就是以后题目一定一定要多看几遍,不清楚要和队友讨论下。代码如下,聪明的猴子的话要改下输入那里。
/*
* 大数模版
* 完美支持负数及加减法操作
* 支持乘法,大小比较,赋值
* 支持与long long类型的赋值比较
* SF-_- 14.04.01
*/
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int K = 10000; // 数组里每位代表1W
const int M = 300; // 一共10位
const char show[] = "%04lld";
struct Bignum
{
LL a[M*2]; // 大数数组
int len; // 长度
bool negative; // 正负
Bignum()
{
clear();
}
void clear()
{
len=0;
negative=false;
memset(a, 0, sizeof(a));
}
Bignum(LL num)
{
*this=num;
}
Bignum operator=(LL num)
{
clear();
if(num<0) negative=true, num=-num;
while(num)
a[len++]=num%K,num/=K;
return *this;
}
Bignum(const Bignum& cmp)
{
memcpy(this, &cmp, sizeof(Bignum));
}
Bignum operator=(const Bignum& cmp)
{
memcpy(this, &cmp, sizeof(Bignum));
return *this;
}
int absCmp(const Bignum& cmp)
{
if(len!=cmp.len)
return len>cmp.len?1:-1;
for(int i=len-1;i>=0;i--)
if(a[i]!=cmp.a[i])
return a[i]>cmp.a[i]?1:-1;
return 0;
}
int absCmp(LL num)
{
Bignum cmp(num);
return absCmp(cmp);
}
bool operator<(const Bignum& cmp)
{
if(negative^cmp.negative)
return negative?true:false;
if(negative)
return absCmp(cmp)>0;
else
return absCmp(cmp)<0;
}
bool operator<(LL num)
{
Bignum cmp(num);
return *this<cmp;
}
bool operator==(const Bignum& cmp)
{
if(negative^cmp.negative)
return false;
return absCmp(cmp)==0;
}
bool operator==(LL num)
{
Bignum cmp(num);
return *this==cmp;
}
void absAdd(const Bignum& one, const Bignum& two)
{
len=max(one.len, two.len);
for(int i=0;i<len;i++)
{
a[i]+=one.a[i]+two.a[i];
if(a[i]>=K) a[i]-=K, a[i+1]++;
}
if(a[len]) len++;
}
void absSub(const Bignum& one, const Bignum& two)
{
len=one.len;
for(int i=0;i<len;i++)
{
a[i]+=one.a[i]-two.a[i];
if(a[i]<0) a[i+1]--,a[i]+=K;
}
while(len>0 && a[len-1]==0) len--;
}
void absMul(const Bignum& one, const Bignum& two)
{
len=one.len+two.len;
for(int i=0;i<one.len;i++) for(int j=0;j<two.len;j++)
a[i+j]+=one.a[i]*two.a[j];
for(int i=0;i<len;i++) if(a[i]>=K)
a[i+1]+=a[i]/K,a[i]%=K;
while(len>0 && a[len-1]==0) len--;
}
Bignum operator+(const Bignum& cmp)
{
Bignum c;
if(negative^cmp.negative)
{
bool res = absCmp(cmp)>0;
c.negative = !(negative^res);
if(res)
c.absSub(*this, cmp);
else
c.absSub(cmp, *this);
}
else if(negative)
{
c.negative=true;
c.absAdd(*this, cmp);
}
else
{
c.absAdd(*this, cmp);
}
return c;
}
Bignum operator-(const Bignum& cmp)
{
Bignum cpy;
if(cpy==cmp)
return *this;
else
cpy=cmp, cpy.negative^=true;
return *this+cpy;
}
Bignum operator*(const Bignum& cmp)
{
Bignum c;
if(c==cmp || c==*this)
return c;
c.negative = negative^cmp.negative;
c.absMul(*this, cmp);
return c;
}
void output()
{
if(len==0)
{
puts("0");
return;
}
if(negative)
printf("-");
printf("%lld", a[len-1]);
for(int i=len-2;i>=0;i--)
printf(show, a[i]);
puts("");
}
};
Bignum quickPow(Bignum a, LL b)
{
Bignum res = 1;
while(b)
{
if(b&1)
res = res*a;
a=a*a;
b>>=1;
}
return res;
}
int factor[33];
int factorNum;
void decompostion(int n)
{
factorNum = 0;
int m=(int)(sqrt(n+0.0)+0.5);
for(int i=2;i<=m;i++) if(n%i==0)
{
factor[factorNum++]=i;
while(n%i==0) n/=i;
}
if(n>1) factor[factorNum++]=n;
}
void work(int n, int m)
{
decompostion(m);
Bignum ans = quickPow(m, n);
for(int i=1;i<(1<<factorNum);i++)
{
int tmp=1;
bool flag=false;
for(int j=0;j<factorNum;j++) if(i&(1<<j))
tmp = tmp*factor[j], flag=!flag;
if(flag)
ans = ans - quickPow(m/tmp, n);
else
ans = ans + quickPow(m/tmp, n);
}
ans.output();
}
int main()
{
int n, m;
while(~scanf("%d%d", &n, &m))
work(n, m);
}