题解 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;
}