题目
问题描述
我们以
[
b
,
q
,
y
]
[b,q,y]
[b,q,y]表示以
b
b
b为首元素,
q
q
q为公差,
y
y
y为序列个数的序列,如
[
−
1
,
2
,
4
]
[-1,2,4]
[−1,2,4]表示序列
[
−
1
,
1
,
3
,
5
]
[-1,1,3,5]
[−1,1,3,5]。
若存在两个序列
A
A
A、
B
B
B,它们的交集为序列
C
C
C,在我们已知序列
B
B
B、
C
C
C的前提下,问
A
A
A有多少种可能:
若不存在,则输出
0
0
0;
若存在无限个,则输出
−
1
-1
−1;
否则,输出具体数目,答案可能过大,对答案模上
1
0
9
+
7
10^9+7
109+7。
分析
1.不存在
当
C
C
C中存在
B
B
B中不存在的元素时,说明序列
C
C
C不合法。
判断
C
C
C是否包含于
B
B
B中,先看范围,再看首部对应,最后看公差关系。
目标是保证
C
C
C中每一项在
B
B
B中均有对应。
bool surplus(){//看范围,再看首尾,再看公差关系
if(c<b)return true;
if(c+r*(z-1)>b+q*(y-1))return true;
if((c-b)%q!=0||(c-b+r*(z-1))%q!=0||r%q!=0)return true;
return false;
}
2.无限个
序列
A
A
A有无限种可能,也就是其个数的增加不会影响
C
C
C的值,也就是这些值不会位于
B
B
B中。
当
b
>
c
−
r
b>c-r
b>c−r,形如
c
−
r
∗
i
(
1
<
i
)
c-r*i(1<i)
c−r∗i(1<i)的元素可以被包含于
A
A
A中,且对结果没有影响,所以序列
A
A
A个数不受限制,序列可能为无限种;
当
b
+
q
∗
(
y
−
1
)
<
c
+
r
∗
z
b+q*(y-1)<c+r*z
b+q∗(y−1)<c+r∗z,同理。
if(b>c-r||b+q*(y-1)<c+r*z){//a立足于c,a中可以含有无限个b中不含的元素,左拓或右拓,
cout<<"-1"<<endl;
return;
}
3.有限个
我们以
[
a
,
p
,
x
]
[a,p,x]
[a,p,x]来表示序列
A
A
A,此时必定满足
l
c
m
(
p
,
q
)
=
r
lcm(p,q)=r
lcm(p,q)=r,根据式子
r
=
p
∗
q
g
c
d
(
p
,
q
)
r=\frac{p*q}{gcd(p,q)}
r=gcd(p,q)p∗q可以看出
p
p
p一定是
r
r
r的因子,此时通过
O
(
r
)
O(\sqrt{r})
O(r)的时间可以枚举出
r
r
r所有的因子,再以辗转相除法确定是否满足
r
=
p
∗
q
g
c
d
(
p
,
q
)
r=\frac{p*q}{gcd(p,q)}
r=gcd(p,q)p∗q。
若我们得到一个
p
p
p满足式子,接下来的问题就是在
A
A
A于此下有多少个满足要求的解?
为了保证
C
C
C的合法性,我们所得的
a
a
a与
x
x
x也应当有所约束:
1.
a
>
c
−
r
&
&
a
+
p
∗
(
x
−
1
)
<
c
+
r
∗
z
a>c-r\&\&a+p*(x-1)<c+r*z
a>c−r&&a+p∗(x−1)<c+r∗z
我们已知此时
B
B
B与
C
C
C满足
:
b
≤
c
−
r
&
&
c
+
r
∗
z
≤
b
+
q
∗
(
y
−
1
)
:\ \ b\leq c-r\&\& c+r*z\leq b+q*(y-1)
: b≤c−r&&c+r∗z≤b+q∗(y−1),若
A
A
A不满足要求,
C
C
C将不合法。
2.
(
c
−
a
)
%
p
=
=
0
(c-a)\%p==0
(c−a)%p==0
首部对应,保证
C
C
C中每一项在
A
A
A中均有对应。
由条件1可知,
a
a
a可以选择的位置为
[
c
−
r
+
1
,
c
−
r
+
2....
,
c
−
1
,
c
]
[c-r+1,c-r+2....,c-1,c]
[c−r+1,c−r+2....,c−1,c],共计
r
r
r个位置,又因条件2,所以共有
r
p
\frac{r}{p}
pr个合法位置;
同理右端
a
+
p
∗
(
x
−
1
)
a+p*(x-1)
a+p∗(x−1)也有
r
p
\frac{r}{p}
pr个位置可以选择,共计有
(
r
p
)
2
(\frac{r}{p})^2
(pr)2种方案。
总和就是 ∑ l c m ( p , q ) = r ( r p ) 2 \sum_{lcm(p,q)=r}(\frac{r}{p})^2 ∑lcm(p,q)=r(pr)2
代码
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
#define fir(i, a, b) for (ll i = (a); i <= (b); i++)
#define rif(i, a, b) for (ll i = (a); i >= (b); i--)
const int N=3e5;
const ll mod=1e9+7;
ll b,q,y,c,r,z,cnt,tmp;
ll gcd(ll x,ll y){
return y?gcd(y,x%y):x;
}
ll lcm(ll x,ll y){
return x*y/gcd(x,y);
}
bool surplus(){//看范围,再看首尾,再看公差关系
if(c<b)return true;
if(c+r*(z-1)>b+q*(y-1))return true;
if((c-b)%q!=0||r%q!=0)return true;
return false;
}
inline void solve(){
cin>>b>>q>>y>>c>>r>>z;
if(surplus()){
cout<<0<<endl;
return;
}
if(b>c-r||b+q*(y-1)<c+r*z){//a立足于c,a中可以含有无限个b中不含的元素,左拓或右拓,
cout<<"-1"<<endl;
return;
}
cnt=0;//此时特点为C首尾元素不为b首尾元素,枚举a可能公差值x,满足x*q/gcd(x,q)=r--> x为r因子,
for(ll i=1;i*i<=r;i++){
if(r%i==0){//同时讨论两个因子,i与r/i,注意避免重复讨论
if(lcm(i,q)==r){
(cnt+=(r/i)*(r/i))%=mod;
}
tmp=r/i;
if(lcm(tmp,q)==r&&tmp!=i){
(cnt+=(r/tmp)*(r/tmp))%=mod;
}
}
}
cout<<cnt<<endl;
}
int main(){
ll _;
cin>>_;
// _=1;
while(_--){
solve();
}
return 0;
}