description
- 有
m
m
个数a[1..m],对于
a[i]
a
[
i
]
,我们可以知道
∑k∗a[i]i=(k−1)∗a[i]+1x[i](k∗a[i]<=n)
∑
i
=
(
k
−
1
)
∗
a
[
i
]
+
1
k
∗
a
[
i
]
x
[
i
]
(
k
∗
a
[
i
]
<=
n
)
以及
- 前n个数的和,问我们能确定几个
x[i]
x
[
i
]
40points
-
sum[i]=∑ni=1x[i]
s
u
m
[
i
]
=
∑
i
=
1
n
x
[
i
]
- 如果知道
sum[i]和sum[i−1],那么我们就可以确定x[i]
s
u
m
[
i
]
和
s
u
m
[
i
−
1
]
,
那
么
我
们
就
可
以
确
定
x
[
i
]
- 结论显然
-
如果知道区间[l..r],区间[l..i−1],区间[i+1..r]各自的和,那也可以知道x[i]
如
果
知
道
区
间
[
l
.
.
r
]
,
区
间
[
l
.
.
i
−
1
]
,
区
间
[
i
+
1..
r
]
各
自
的
和
,
那
也
可
以
知
道
x
[
i
]
-
但区间[i+1..r]前面区间一定有区间[x..i],所以结论证毕
但
区
间
[
i
+
1..
r
]
前
面
区
间
一
定
有
区
间
[
x
.
.
i
]
,
所
以
结
论
证
毕
-
所以我们对每个a[i]把他的倍数bz一下,这说明他的倍数的前缀和可以确定
所
以
我
们
对
每
个
a
[
i
]
把
他
的
倍
数
b
z
一
下
,
这
说
明
他
的
倍
数
的
前
缀
和
可
以
确
定
-
O(∑mi=1⌊na[i]⌋+n)
O
(
∑
i
=
1
m
⌊
n
a
[
i
]
⌋
+
n
)
100points
-
对于x能否被确定,显然可以列方程
对
于
x
能
否
被
确
定
,
显
然
可
以
列
方
程
-
x mod a[i]=0
x
m
o
d
a
[
i
]
=
0
-
x mod a[j]=1
x
m
o
d
a
[
j
]
=
1
-
是不是列m2个方程,求可行解就可以了?!!
是
不
是
列
m
2
个
方
程
,
求
可
行
解
就
可
以
了
?
!
!
-
会算重!!!
会
算
重
!
!
!
-
那么我们就枚举第i个数是选结果为0的方程(放A集合),结果为1的方程(放B集合),还是不选
那
么
我
们
就
枚
举
第
i
个
数
是
选
结
果
为
0
的
方
程
(
放
A
集
合
)
,
结
果
为
1
的
方
程
(
放
B
集
合
)
,
还
是
不
选
-
然后列方程后对于结果相同的,可以用lcm来合并
然
后
列
方
程
后
对
于
结
果
相
同
的
,
可
以
用
l
c
m
来
合
并
-
最后用拓展gcd算出解的个数∗(−1)|A|+|B|
最
后
用
拓
展
g
c
d
算
出
解
的
个
数
∗
(
−
1
)
|
A
|
+
|
B
|
-
证如果x合法,只会算1次
证
如
果
x
合
法
,
只
会
算
1
次
-
∑|A|i=1Ci|A|∑|B|i=1Ci|B|(−1)i+j
∑
i
=
1
|
A
|
C
|
A
|
i
∑
i
=
1
|
B
|
C
|
B
|
i
(
−
1
)
i
+
j
-
=∑|A|i=1Ci|A|(−1)i∑|B|j=1Cj|B|(−1)j
=
∑
i
=
1
|
A
|
C
|
A
|
i
(
−
1
)
i
∑
j
=
1
|
B
|
C
|
B
|
j
(
−
1
)
j
-
=((1−1)|A|−1)∗((1−1)|B|−1)
=
(
(
1
−
1
)
|
A
|
−
1
)
∗
(
(
1
−
1
)
|
B
|
−
1
)
-
=1
=
1
using namespace std;
const ll maxN=20;
ll n,m,i,j,ii,jj,sum1,ans,a[maxN],bz;
ll gcd(ll x,ll y){
return (x%y==0)?y:gcd(y,x%y);
}
ll lcm(ll x,ll y){
i=gcd(x,y);
return x/i*y;
}
void exgcd(ll xx,ll yy){
if (yy==0){
i=1,j=0;
return;
}
exgcd(yy,xx%yy);
ii=i,jj=j;
i=-jj,
j=-ii-(xx/yy)*jj;
}
void dfs(ll t,ll x,ll y,ll sum){
if (gcd(x,y)!=1) return;
if (x>n || y>n) return;
if (t>m){
if (x==1 || y==1) return;
exgcd(x,y);
i=(i%y+y)%y;
j=n/x;
if (j<i){
return;
}
sum1=(j-i)/y;
sum1+=(j>=i);
ans+=sum*sum1;
if (j*x==n && (j-i)%y==0){
bz=0;
}
return;
}
dfs(t+1,lcm(a[t],x),y,-sum);
dfs(t+1,x,lcm(a[t],y),-sum);
dfs(t+1,x,y,sum);
}
int main(){
freopen("sazetak.in","r",stdin);
freopen("sazetak.out","w",stdout);
scanf("%lld%lld",&n,&m);
fo(i,1,m) scanf("%lld",&a[i]);
bz=1;
dfs(1,1,1,1);
fo(i,1,m)
if ((n-1)%a[i]==0) ans+=bz;
printf("%lld",ans);
}