题解 T2最简单辣快来做

传送门

  • 关于exgcd:exgcd(a, b, x, y) 可以求解一组方程 \(ax+by\equiv gcd(a, b)\)合法解
    若想求最小整数解记得 \((x\%mod+mod)\%mod\)

于是有50pts部分分可以exgcd求逆搭配二维前缀和来做

全分的话肯定还是二维前缀和,但没办法求逆了

  • 处理给定点与整个二维平面上多个给定点间运算结果的新思路:
    发现指数上的绝对值只在跨越一个出现过的横/纵坐标的时候发生变化,所以所有出现过的横/纵坐标会将平面划分为 \(n^2\) 个区域
    在每个区域内相对大小关系不变,只在(九宫格范围内)四个角的矩形内有其它点
    且像这样 \(\sum h_i*a^{|x-p|}*b^{|y-q|}\) 的式子还可以同时乘上 \(a, b\) 的幂次来实现在小区域内的移动
    具体实现的话可以令 \(sum[1...4][i][j]\) 为网格点上四个方向的前缀和,需要特判查询点恰好落在网格点上的情况
  • 关于光速幂:
    ll pow1[N], pow2[N];
    void init() {
    	ll len=sqrt(1e10);
    	pow1[0]=pow2[0]=1%mod;
    	for (int i=1; i<=len; ++i) pow1[i]=pow1[i-1]*base%mod;
    	for (int i=1; i<=len; ++i) pow2[i]=pow2[i-1]*pow1[len]%mod;
    }
    ll lpow(ll a, ll b) {return b<=len?pow1[len]:pow2[b/len]*pow1[b-b/len*len]%mod;}
    

于是这个题就做完了

Code:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 200010
#define ll long long
//#define int long long

char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
	int ans=0, f=1; char c=getchar();
	while (!isdigit(c)) {if (f=='-') f=-f; c=getchar();}
	while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
	return ans*f;
}

int n, m;
ll w, d, mod, a, b, h[N], x[N], y[N];
inline ll qpow(ll a, ll b) {ll ans=1ll; for (; b; b>>=1,a=a*a%mod) if (b&1) ans=ans*a%mod; return ans;}

namespace force{
	void solve() {
		ll p, q, ans;
		for (int i=1; i<=m; ++i) {
			p=read(); q=read(); ans=0;
			for (int j=1; j<=n; ++j) {
				ans=(ans+h[j]*qpow(a, llabs(p-x[j]))%mod*qpow(b, llabs(q-y[j]))%mod)%mod;
			}
			printf("%lld\n", ans);
		}
		exit(0);
	}
}

namespace task1{
	int uni[N], usize;
	int sum[5][4010][4010];
	inline ll qsum(int i, int x1, int y1, int x2, int y2) {return 1ll*sum[i][x2][y2]-sum[i][x1-1][y2]-sum[i][x2][y1-1]+sum[i][x1-1][y1-1];}
	inline void exgcd(ll a, ll b, ll& x, ll& y) {
		if (!b) {x=1; y=0; return ;}
		exgcd(b, a%b, y, x);
		y-=(a/b)*x;
	}
	inline ll inv(ll a) {
		ll x, y;
		exgcd(a, mod, x, y);
		return (x%mod+mod)%mod;
	}
	void solve() {
		cout<<double(sizeof(sum))/1024/1024<<endl;
		for (int i=1; i<=n; ++i) uni[++usize]=x[i], uni[++usize]=y[i];
		sort(uni+1, uni+usize+1);
		usize=unique(uni+1, uni+usize+1)-uni-1;
		for (int i=1; i<=n; ++i) {
			cout<<"i: "<<i<<endl;
			int x1=lower_bound(uni+1, uni+usize+1, x[i])-uni, y1=lower_bound(uni+1, uni+usize+1, y[i])-uni;
			cout<<"xy: "<<x1<<' '<<y1<<endl;
			ll ax=qpow(a, x1), by=qpow(b, y1), iax=inv(ax), iby=inv(by);
			sum[1][x1][y1]=(sum[1][x1][y1]+by*qpow(ax, mod-2)%mod)%mod;
			sum[2][x1][y1]=(sum[2][x1][y1]+qpow(ax*by%mod, mod-2))%mod;
			sum[3][x1][y1]=(sum[3][x1][y1]+ax*qpow(by, mod-2)%mod)%mod;
			sum[4][x1][y1]=(sum[4][x1][y1]+ax*by%mod)%mod;
		}
		ll p, q, ans;
		cout<<"step2: "<<endl;
		for (int i=1; i<=m; ++i) {
			cout<<"i: "<<i<<endl;
			p=read(); q=read(); ans=0;
			ll ap=qpow(a, p), bq=qpow(b, q), iap=qpow(ap, mod-2), ibq=qpow(bq, mod-2);
			ll t2;
			exgcd(ap, mod, iap, t2);
			exgcd(bq, mod, ibq, t2);
			iap=(iap%mod+mod)%mod; ibq=(ibq%mod+mod)%mod;
			cout<<"test: "<<ap*iap%mod<<endl;
			for (int j=1; j<=n; ++j) {
				int x1=upper_bound(uni+1, uni+usize+1, p)-uni-1, y1=upper_bound(uni+1, uni+usize+1, q)-uni-1;
				ans=(ans+ap*ibq%mod*qsum(1, 1, y1+1, x1, usize)%mod)%mod;
				ans=(ans+ap*bq%mod*qsum(2, 1, 1, x1, y1)%mod)%mod;
				ans=(ans+bq*iap%mod*qsum(3, x1+1, 1, usize, y1)%mod)%mod;
				ans=(ans+ibq*iap%mod*qsum(4, x1+1, y1+1, usize, usize)%mod)%mod;
			}
			printf("%lld\n", ans);
		}
		exit(0);
	}
}

namespace task{
	#undef unix
	int unix[N], uniy[N], usizx, usizy;
	ll sum[5][2010][2010], val[2010][2010], apow1[N], apow2[N], bpow1[N], bpow2[N], len;
	void init() {
		len=sqrt(1e10);	
		apow1[0]=apow2[0]=1%mod; bpow1[0]=bpow2[0]=1%mod;
		for (int i=1; i<=len; ++i) apow1[i]=apow1[i-1]*a%mod, bpow1[i]=bpow1[i-1]*b%mod;
		for (int i=1; i<=len; ++i) apow2[i]=apow2[i-1]*apow1[len]%mod, bpow2[i]=bpow2[i-1]*bpow1[len]%mod;
	}
	inline ll lpow(ll x, ll y) {
		if (x==a) return y<=len?apow1[y]:apow2[y/len]*apow1[y-y/len*len]%mod;
		else return y<=len?bpow1[y]:bpow2[y/len]*bpow1[y-y/len*len]%mod;
	}
	void solve() {
		init();
		for (int i=1; i<=n; ++i) unix[++usizx]=x[i], uniy[++usizy]=y[i];
		unix[++usizx]=0; unix[++usizx]=1e9+7; uniy[++usizy]=0; uniy[++usizy]=1e9+7;
		sort(unix+1, unix+usizx+1); sort(uniy+1, uniy+usizy+1);
		usizx=unique(unix+1, unix+usizx+1)-unix-1; usizy=unique(uniy+1, uniy+usizy+1)-uniy-1;
		for (int i=1; i<=n; ++i) {
			int x2=lower_bound(unix+1, unix+usizx+1, x[i])-unix, y2=lower_bound(uniy+1, uniy+usizy+1, y[i])-uniy;
			for (int j=1; j<=4; ++j) sum[j][x2][y2]+=h[i];
			val[x2][y2]+=h[i];
		}
		for (int i=1; i<usizx; ++i) {
			for (int j=usizy-1; j; --j) {
				// cout<<unix[i]<<' '<<uniy[j]<<endl;
				sum[1][i][j] = (sum[1][i][j]+sum[1][i-1][j]*lpow(a, unix[i]-unix[i-1])%mod+sum[1][i][j+1]*lpow(b, uniy[j+1]-uniy[j])%mod-sum[1][i-1][j+1]*lpow(a, unix[i]-unix[i-1])%mod*lpow(b, uniy[j+1]-uniy[j])%mod)%mod;
				// printf("sum[1][%d][%d]=%lld\n", i, j, sum[1][i][j]);
			}
		}
		for (int i=1; i<usizx; ++i) {
			for (int j=1; j<usizy; ++j) {
				sum[2][i][j] = (sum[2][i][j]+sum[2][i-1][j]*lpow(a, unix[i]-unix[i-1])%mod+sum[2][i][j-1]*lpow(b, uniy[j]-uniy[j-1])%mod-sum[2][i-1][j-1]*lpow(a, unix[i]-unix[i-1])%mod*lpow(b, uniy[j]-uniy[j-1])%mod)%mod;
			}
		}
		for (int i=usizx-1; i; --i) {
			for (int j=1; j<usizy; ++j) {
				sum[3][i][j] = (sum[3][i][j]+sum[3][i+1][j]*lpow(a, unix[i+1]-unix[i])%mod+sum[3][i][j-1]*lpow(b, uniy[j]-uniy[j-1])%mod-sum[3][i+1][j-1]*lpow(a, unix[i+1]-unix[i])%mod*lpow(b, uniy[j]-uniy[j-1])%mod)%mod;
			}
		}
		for (int i=usizx-1; i; --i) {
			for (int j=usizy-1; j; --j) {
				sum[4][i][j] = (sum[4][i][j]+sum[4][i+1][j]*lpow(a, unix[i+1]-unix[i])%mod+sum[4][i][j+1]*lpow(b, uniy[j+1]-uniy[j])%mod-sum[4][i+1][j+1]*lpow(a, unix[i+1]-unix[i])%mod*lpow(b, uniy[j+1]-uniy[j])%mod)%mod;
			}
		}
		// cout<<unix[2]<<' '<<uniy[2]<<endl;
		// cout<<sum[1][2][2]+sum[2][2][2]+sum[3][2][2]+sum[4][2][2]<<endl;
		// cout<<sum[1][2][2]<<' '<<sum[2][2][2]<<' '<<sum[3][2][2]<<' '<<sum[4][2][2]<<endl;
		ll p, q, ans;
		for (int i=1; i<=m; ++i) {
			p=read(); q=read(); ans=0;
			int x2=upper_bound(unix+1, unix+usizx+1, p)-unix, y2=upper_bound(uniy+1, uniy+usizy+1, q)-uniy;
			if (unix[x2]==p && uniy[y2]==q) ans=(sum[1][2][2]+sum[2][2][2]+sum[3][2][2]+sum[4][2][2]-val[x2][y2]*3)%mod;
			else {
				ans = (ans+sum[1][x2-1][y2]*lpow(a, p-unix[x2-1])%mod*lpow(b, uniy[y2]-q)%mod)%mod;
				ans = (ans+sum[2][x2-1][y2-1]*lpow(a, p-unix[x2-1])%mod*lpow(b, q-uniy[y2-1])%mod)%mod;
				ans = (ans+sum[3][x2][y2-1]*lpow(a, unix[x2]-p)%mod*lpow(b, q-uniy[y2-1])%mod)%mod;
				ans = (ans+sum[4][x2][y2]*lpow(a, unix[x2]-p)%mod*lpow(b, uniy[y2]-q)%mod)%mod;
			}
			printf("%lld\n", (ans%mod+mod)%mod);
		}
		exit(0);
	}
}

signed main()
{
	freopen("satellite.in", "r", stdin);
	freopen("satellite.out", "w", stdout);

	n=read(); m=read(); w=read(); d=read(); mod=read(); a=read(); b=read();
	for (int i=1; i<=n; ++i) {h[i]=read(); x[i]=read(); y[i]=read();}
	// force::solve();
	task::solve();

	return 0;
}
posted @ 2021-10-09 20:00  Administrator-09  阅读(3)  评论(0编辑  收藏  举报