#Description
有一个未知的序列x,长度为n。它的K-划分序列y指的是每连续K个数的和得到划分序列,y[1]=x[1]+x[2]+…+x[K],y[2]=x[K+1]+x[K+2]+…+x[K+K]…。若n不被K整除,则y[n/K+1]可以由少于K个数加起来。比如n=13,K=5,则y[1]=x[1]+…+x[5],y[2]=x[6]+…+x[10],y[3]=x[11]+x[12]+x[13]。若小A只确定x的K[1]划分序列以及K[2]划分序列…K[M]划分序列的值情况下,问她可以确定x多少个元素的值。
#Input
第一行输入两个正整数n,M。
第二行输入M个正整数表示K[1],K[2]…K[M]。
#Output
输出1个整数,表示能确定的元素
#Sample Input
【输入样例1】
3 1
2
【输入样例2】
6 2
2 3
【输入样例3】
123456789 3
5 6 9
#Sample Output
【输出样例1】
1
【输出样例2】
2
【输出样例3】
10973937
#Data Constraint
对于20%的数据,3 <= N <= 2000,M<=3。
对于40%的数据,3 <= N <= 5*10^6。
对于100%的数据,3 <= N <= 10^9 , 1 <= M <= 10,2 <= K[i] < N。
#Hint
【样例1解释】
小A知道x的2-划分序列,即分别知道x[1]+x[2],x[3]的值。
小A可以知道x[3]的值。
【样例2解释】
小A知道x的2-划分序列,即分别知道x[1]+x[2],x[3]+x[4],x[5]+x[6] 的值。
小A知道x的3-划分序列,即分别知道x[1]+x[2]+x[3] ,x[4]+x[5]+x[6] 的值。
小A可以知道x[3],x[4]的值,个数为2.
#题解
这题在考场的时候由于T1水题的错误理解导致心态崩了。
于是T3(这道题)就很少时间+很少心情去想。
只是在纸上推了推,然后就几乎弃掉了。
然而我推出了个公式——
满足xk[i]-1=yk[j]时,大概是对答案造成n div (k[i]*k[j])的贡献。
然而这就是关键!
满足的式子我们可以换一下,变成拓展欧几里得来求。
然后那个答案其实我算错了:是
1+(n-k[i]*x)/(k[i]*k[j])
然后,这样可以在一个m方级别的时间复杂度完成。
但是,我们可以很难受地发现,会有一些计算重复。
怎么办?我们就直接搞容斥原理即可。
原式:ax-by=1
那么我们就可以分为3类——
分到a集合。
分到b集合。
不分。
这样就可以状压DP。
其实dfs即可,更好写。
我们就看看如何容斥。
首先,我们可以发现,当两个集合的和为偶数,则是对答案造成贡献。奇数则为删除重复。
这个可以自己推一推。
然后,我们每次更新答案的时候,就把a集合的数全部求lcm。b集合的数全部求lcm。
然后两个拓展欧几里得一下。
就可以更新啦~~~
但是,看到第一个样例。这种情况要搞一搞。实际上直接把n丢在dfs的队列里面即可。
然而,我蜜汁错误90.有一点一直没调出来,只好低(man)头(xing)叹(huan)息(xi)地打了个表。
如果有大佬找到错误了,可以在下面帮我求解。万分感谢。
错误的代码
var
i,j,k,l,n,m:longint;
zb,yb,gs1,gs2:int64;
x,y,aa,bb,cc,dd,ans:int64;
a,zt:array[1..11] of int64;
function exgcd(a,b:int64):int64;
var
r,z:int64;
begin
if b=0 then
begin
x:=1;
y:=0;
exit(a);
end;
r:=exgcd(b,a mod b);
z:=x;
x:=y;
y:=z-a div b*y;
exit(r);
end;
function gcd(x,y:int64):int64;
begin
if y=0 then exit(x);
exit(gcd(y,x mod y));
end;
function lcm(x,y:int64):int64;
var
i:qword;
begin
i:=x*y;
exit(i div gcd(x,y));
end;
procedure dfs(dep:longint);
var
j,k,l:longint;
i:int64;
begin
if dep>m+1 then
begin
if (gcd(zb,yb)=1) and (gs1>0) and (gs2>0) then
begin
if (gs1+gs2) mod 2=0 then
begin
x:=0;
y:=0;
aa:=zb;
bb:=-yb;
cc:=1;
dd:=exgcd(aa,bb);
if cc mod dd=0 then
begin
x:=x*cc div dd mod (bb div dd);
if x<0 then
x:=x+abs(bb div dd);
y:=(cc-aa*x) div bb;
if (aa*x<=n) then
if y>0 then ans:=ans+1+(n-aa*x+1) div (aa*(-bb));
end;
end
else
begin
x:=0;
y:=0;
aa:=zb;
bb:=-yb;
cc:=1;
dd:=exgcd(aa,bb);
if cc mod dd=0 then
begin
x:=x*cc div dd mod (bb div dd);
if x<0 then
x:=x+abs(bb div dd);
y:=(cc-aa*x) div bb;
if (aa*x<=n) then
if y>0 then ans:=ans-1-(n-aa*x+1) div (aa*(-bb));
end;
end;
end;
end
else
begin
i:=zb;
zb:=lcm(zb,a[dep]);
inc(gs1);
if zb