题目链接:http://codeforces.com/gym/102769/problem/I
一开始想到贝祖定理,但是只能分别判断x和y方向上的,没办法组合起来判断。
思路分析
这道题考的其实主要不是贝祖定理,而是exgcd。
假设我现在我们有向量
(
a
1
,
b
1
)
,
(
a
2
,
b
2
)
(a_1,b_1),(a_2,b_2)
(a1,b1),(a2,b2)。
考虑x方向上,若某横坐标c可以到达,则表示存在x,y,使得
a
1
x
+
a
2
y
=
c
a_1x+a_2y=c
a1x+a2y=c。由exgcd可知:该方程解的情况等价于
a
2
x
+
(
a
1
−
a
2
)
y
=
c
a_2x+({a1- a2})y=c
a2x+(a1−a2)y=c解的情况。
并且,通过更损相减法我们可以知道,一直mod递归下去,a1和a2中最后会有一个变为0,因此,我们可以知道:两个数a,b线性组合是否有解等价于b,a-tb的线性组合是否有解。
通过上面的思考,我们将这个想法拓展到二维的向量a,b上:那也一定有
a
x
+
b
y
=
c
ax+by=c
ax+by=c解的情况等价于
b
x
+
(
a
−
b
)
y
=
c
bx+(a-b)y=c
bx+(a−b)y=c的解的情况(将两维分开来看就可以懂了)。因此,我们可以利用这个式子,把a的x变成0,这样横坐标上只有b向量有贡献,就很好判断了。
这个思想甚至可以用在更高维度的向量问题上。
总结:k个n维向量的线性组合是否等价于某一n维向量,解的情况等价于n个n维向量线性组合是否等于该n维向量的解的情况。
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define IOS ios_base::sync_with_stdio(0); cin.tie(0);
#define rep(i, a, n) for(int i = a; i <= n; ++ i)
#define per(i, a, n) for(int i = n; i >= a; -- i)
//#define ONLINE_JUDGE
using namespace std;
typedef long long ll;
const int mod=1e9+7;
template<typename T>void write(T x)
{
if(x<0)
{
putchar('-');
x=-x;
}
if(x>9)
{
write(x/10);
}
putchar(x%10+'0');
}
template<typename T> void read(T &x)
{
x = 0;char ch = getchar();ll f = 1;
while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
int lcm(int a,int b){return a/gcd(a,b)*b;};
ll ksm(ll a,ll n){
ll ans=1;
while(n){
if(n&1) ans=(ans*a)%mod;
a=a*a%mod;
n>>=1;
}
return ans%mod;
}
//==============================================================
#define int ll
int t,q;
struct node{
int x,y;
node(int X=0,int Y=0){
x=X;
y=Y;
}
};
void merge(node&a,node&b){
if(!a.x&&!b.x){
b.y=__gcd(b.y,a.y);
a={0,0};
}
else if(!a.y&&!b.y){
b.x=__gcd(a.x,b.x);
a={0,0};
}
while(a.x!=0){
int t=b.x/a.x;
b.x-=t*a.x;
b.y-=t*a.y;
swap(a,b);
}
a.y=abs(a.y);
if(b.x<0)b.x=-b.x,b.y=-b.y;
if(a.y)b.y=(b.y%a.y+a.y)%a.y;
}
//b.x为0
bool check(node&a,node&b,int x,int y){
//cerr<<a.x<<" "<<a.y<<" "<<b.x<<" "<<b.y<<" "<<x<<" "<<y<<endl;
int t;
if(a.x==0){
if(x)return false;
else t=0;
}
else t=x/a.x;
//cerr<<t<<endl;
x-=t*a.x;
y-=t*a.y;
if(x)return false;
if(b.y==0)return y==0;
else return y%b.y==0;
}
ll solve(){
ll res=0;
node a,b;
for(int i=0;i<q;++i){
//cerr<<i<<endl;
//cerr<<i<<":"<<endl;;
//cerr<<a.x<<" "<<a.y<<endl;
//cerr<<b.x<<" "<<b.y<<endl;
int opt;read(opt);
if(opt==1){
int x,y;
read(x),read(y);
if(a.x==0&&a.y==0)a.x=x,a.y=y;
else if(b.x==0&&b.y==0){
b.x=x;b.y=y;
merge(b,a);
}
else{
node t(x,y);
merge(t,a);
merge(t,b);
merge(b,a);
}
}
else{
int x,y,w;
read(x),read(y),read(w);
if(check(a,b,x,y))res=res+1ll*w;
}
}
return res;
}
signed main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
//clock_t c1 = clock();
//===========================================================
read(t);
int kase=0;
while(t--){
read(q);
printf("Case #%lld: ",++kase);write(solve());putchar('\n');
}
//===========================================================
//std::cerr << "Time:" << clock() - c1 << "ms" << std::endl;
return 0;
}