虽然这道题正解是容斥
查看原帖
虽然这道题正解是容斥
939957
wanjiabao楼主2025/7/24 18:45

但扩欧肯定能做,有题解为证:link

然后我就调吐了还只有50分。

#include<bits/stdc++.h>
#define int  long long
using namespace std;
int exgcd(int a,int b,int &x,int &y){
	if(b==0){
		x=1,y=0;
		return a;
	}
	int nx,ny;
	int g=exgcd(b,a%b,nx,ny);
	x=ny;
	y=nx-a/b*ny;
	return g;
}
int tx1[100005],ty1[100005],tx2[100005],ty2[100005];
int c1,c2,c3,c4,n;
int pos[100005],len;
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>c1>>c2>>c3>>c4>>n;
	int g1=__gcd(c1,c2),g2=__gcd(c3,c4);
	int addx1=c2/g1,addy1=-c1/g1,addx2=c4/g2,addy2=-c3/g2;
	set<int>acp;
	for(int i=0;i<=100000;i++){
		if(i%g1>0)continue;
		exgcd(c1,c2,tx1[i],ty1[i]);
		tx1[i]*=(i/g1);
		ty1[i]*=(i/g1); 
		if(i%g2>0)continue;
		exgcd(c3,c4,tx2[i],ty2[i]);
		tx2[i]*=(i/g2);
		ty2[i]*=(i/g2); 
		acp.insert(i);
	}
	for(auto x:acp)pos[++len]=x;
	while(n--){
		int d1,d2,d3,d4,s;
		cin>>d1>>d2>>d3>>d4>>s;
		int sum=0;
		for(int l=1;l<=len;l++){
			int i=pos[l];
			if(i>s)continue;
			int x0=tx1[i],y0=ty1[i];
			int xl=0,xr=d1,yl=0,yr=d2;
			int xkl,xkr,ykl,ykr;
			if(addx1>0){
				xkl=ceil(1.0*(xl-x0)/addx1),xkr=floor(1.0*(xr-x0)/addx1);
			}else{
				xkl=ceil(1.0*(xr-x0)/addx1),xkr=floor(1.0*(xl-x0)/addx1);
			}
			if(addy2>0){
				ykl=ceil(1.0*(yl-y0)/addy1),ykr=floor(1.0*(yr-y0)/addy1);
			}else{
				ykl=ceil(1.0*(yr-y0)/addy1),ykr=floor(1.0*(yl-y0)/addy1);
			}
			int kl=max(xkl,ykl),kr=min(xkr,ykr);
			if(kl>kr||xkl>xkr||ykl>ykr)continue;
			int res=(kr-kl+1);
			x0=tx2[s-i],y0=ty2[s-i];
			xl=0,xr=d3,yl=0,yr=d4;
			if(addx2>0){
				xkl=ceil(1.0*(xl-x0)/addx2),xkr=floor(1.0*(xr-x0)/addx2);
			}else{
				xkl=ceil(1.0*(xr-x0)/addx2),xkr=floor(1.0*(xl-x0)/addx2);
			}
			if(addy2>0){
				ykl=ceil(1.0*(yl-y0)/addy2),ykr=floor(1.0*(yr-y0)/addy2);
			}else{
				ykl=ceil(1.0*(yr-y0)/addy2),ykr=floor(1.0*(yl-y0)/addy2);
			}
			kl=max(xkl,ykl),kr=min(xkr,ykr);
			if(kl>kr||xkl>xkr||ykl>ykr)continue;
			res*=(kr-kl+1);
			sum+=res;
		}
		cout<<sum<<"\n";
	}
}

事实证明这题用扩欧做就是石。

2025/7/24 18:45
加载中...