这个东西放在做题笔记里完全不能彰显它的毒瘤,我就单独拿出来了。
题意
有 个圆心为原点,半径为 的圆,定义 为求出每个点被 个圆覆盖的编号和,你需要求出 (答案对 取模)。
样例:5 | 387
, 88 | 16605192
, 888888 | 202495041
, 88888888888 | 143398458
解法
给了我们提示,发现最远被覆盖的点的坐标绝对值不会超过 ,所以我们可以考虑枚举一维,然后 地算出这条线上的答案。
写之前先作一下定义,,也就是 次方前缀和。
首先有一个显然的对称性,也就是一个圆可以分成四个象限来算,最后零点的单独算。
(下文仅考虑一象限和 x 轴的正半轴上)
在第一象限和 x 坐标轴的正半轴上,我们枚举 坐标,然后可以得出在这个点上最高的坐标能取到多少。
假定 可以被取到,总共有 个圆,则它到原点的距离为 ,会被 号圆覆盖,然后因为我们要求 的前缀和,发现若被 号点覆盖,会重复计算 次,若被 号点覆盖,会重复计算 次,依此类推。
所以我们要求的是 。
在零点上,会被所有圆覆盖,所以答案应额外加上 。
然后就开始推式子了。
如果公式有误的话,下面有每一行公式的代码实现,可以先看看代码(都是过了样例的,只是复杂度问题),然后联系我纠正。
可能有点啰嗦,但希望大家看懂,还有就是中间的代码可能得多取模几下,后面调了些东西。
这道题搞得我再也不想推式子了,不过马上就退役了。
这个式子复杂度已经对了,很多地方可以合并之类的,但是我实在推不动了,之后哪天复活把最简化的结果写在下面(?
代码见下。
#include<stdio.h>
#include<math.h>
typedef long long i64;
typedef double f64;
void assert_val(bool val, char* failed) { if(not val) printf("%s FAILED.\n", failed); }
template <const int mod> struct modint;
template <const int mod> modint<mod> pow(modint<mod> x, int p){
modint<mod> re(1);
while(p) {
if(p&1) re*=x;
x*=x; p>>=1;
}
return re;
}
template <const int mod> struct modint{
int x;
modint(int v=0){
if(v<0 or v>=mod) printf("modint::modint<%d>(%d:int) : Error : %d overflow.\n", mod, v, v);
this->x = v;
}
modint<mod> inv() const { return pow(*this, mod-2); }
};
template <const int mod> bool operator==(modint<mod> a, modint<mod> b) { return a.x==b.x; }
template <const int mod> const modint<mod> operator+(modint<mod> a, modint<mod> b) { return modint<mod>(a.x+b.x>=mod?a.x+b.x-mod:a.x+b.x); }
template <const int mod> const modint<mod> operator-(modint<mod> a) { return a.x==0?0:modint<mod>(mod-a.x); }
template <const int mod> const modint<mod> operator-(modint<mod> a, modint<mod> b) { return a + (-b); }
template <const int mod> const modint<mod> operator*(modint<mod> a, modint<mod> b) { return modint<mod>(1ll * a.x * b.x % mod); }
template <const int mod> const modint<mod> operator/(modint<mod> a, modint<mod> b) { return a * b.inv(); }
template <const int mod> const modint<mod> operator+=(modint<mod>& a, modint<mod> b) { return a = a+b; }
template <const int mod> const modint<mod> operator-=(modint<mod>& a, modint<mod> b) { return a = a-b; }
template <const int mod> const modint<mod> operator*=(modint<mod>& a, modint<mod> b) { return a = a*b; }
template <const int mod> const modint<mod> operator/=(modint<mod>& a, modint<mod> b) { return a = a/b; }
//
const int maxn = 10000007;
const int mod = 1000000007;
typedef modint<mod> mi;
i64 ni;
mi res;
const mi I1 = mi(1);
const mi I2 = mi(2);
const mi I3 = mi(3);
const mi I4 = mi(4);
const mi I6 = mi(6);
const mi inv2 = mi(2).inv();
const mi inv6 = mi(6).inv();
struct {mi operator[](mi x){return x*(x+mi(1))*(mi(2)*x+mi(1))*inv6;}} pw2sum;
mi pw4sum[maxn], pw6sum[maxn];
mi p2(mi x) { return x*x; }
mi p4(mi x) { return p2(p2(x)); }
mi p6(mi x) { return p2(p2(x)) * p2(x); }
const f64 eps = 0;
// f64 f (f64 x, i64 l) { return x*x - l; }
// f64 df(f64 x) { return 2.*x; }
// i64 sqrt(i64 x) {
// f64 c = 1;
// for(int i=1;i<=32;i++)
// c = c - f(c, x) / df(c);
// return c + eps;
// }
signed main() {
#ifndef debug_rickyxrc
freopen("circle.in" , "r", stdin );
freopen("circle.out", "w", stdout);
#endif
for(int i=1;i<maxn;i++)
pw4sum[i] = pw4sum[i-1] + p4(i),
pw6sum[i] = pw6sum[i-1] + p6(i);
scanf("%lld", &ni);
mi n = mi(ni % mod);
// int qn = sqrt(ni);
// printf("%d\n", qn);
// printf("%lld\n", i64(qn + eps) * i64(qn + eps));
// return 0;
#if 0 // Iter 1
for(int x=1;x<=sqrt(n);x++)
for(int y=0;y<=sqrt(n-x*x);y++)
for(int k=x*x+y*y;k<=n;k++)
res += mi(k)*mi(n+1-k);
#endif
#if 0 // Iter 2
for(int x=1;x<=qn;x++)
for(int y=0;y<=sqrt(ni-x*x);y++)
for(int ki=x*x+y*y;ki<=ni;ki++) {
mi k = mi(ki);
res += (n+I1) * k - k*k;
}
#endif
#if 0 // Iter 3
for(int x=1;x<=qn;x++)
for(int y=0;y<=sqrt(ni-x*x);y++) {
mi tsum;
for(int ki=x*x+y*y;ki<=ni;ki++) {
mi k = mi(ki);
tsum += k;
}
for(int ki=x*x+y*y;ki<=ni;ki++) {
mi k = mi(ki);
res -= k*k;
}
res += (n+I1)*tsum;
}
#endif
// Iter 4
// for(int xi=1;1ll*xi*xi<=ni;xi++)
// for(int yi=0;yi<=sqrt(ni-1ll*xi*xi);yi++) {
// mi x = mi(xi), y = mi(yi);
// mi tsum;
// tsum = (x*x+y*y+n) * (n-x*x-y*y+I1) * inv2;
// res += (n+I1)*tsum;
// for(int ki=1ll*xi*xi+yi*yi;ki<=ni;ki++) {
// mi k = mi(ki);
// res -= k*k;
// }
// }
// Iter 5
// for(int xi=1;1ll*xi*xi<=ni;xi++)
// for(int yi=0;yi<=sqrt(ni-1ll*xi*xi);yi++) {
// mi x = mi(xi), y = mi(yi);
// mi tsum;
// tsum = (x*x+y*y+n) * (n-x*x-y*y+I1) * inv2;
// res += (n+I1)*tsum;
// for(int ki=1;ki<1ll*xi*xi+yi*yi;ki++) {
// mi k = mi(ki);
// res += k*k;
// }
// for(int ki=1;ki<=ni;ki++) {
// mi k = mi(ki);
// res -= k*k;
// }
// }
// Iter 6
// for(int xi=1;1ll*xi*xi<=ni;xi++)
// for(int yi=0;yi<=sqrt(ni-1ll*xi*xi);yi++) {
// mi x = mi(xi), y = mi(yi);
// res += (n+I1) * (x*x+y*y+n) * (n-x*x-y*y+I1) * inv2;
// res += pw2sum[x*x+y*y-I1], res -= pw2sum[n];
// }
// Iter 7
// for(int xi=1;1ll*xi*xi<=ni;xi++)
// for(int yi=0;yi<=sqrt(ni-1ll*xi*xi);yi++) {
// mi x = mi(xi), y = mi(yi);
// res += (p2(x)+p2(y)-p4(x)-p4(y)-I2*p2(x)*p2(y)+n*(n+I1));
// }
// res *= (n+I1) * inv2;
// for(int xi=1;1ll*xi*xi<=ni;xi++)
// for(int yi=0;yi<=sqrt(ni-1ll*xi*xi);yi++) {
// mi x = mi(xi), y = mi(yi);
// res += pw2sum[x*x+y*y-I1], res -= pw2sum[n];
// }
// Iter 8
// for(int xi=1;1ll*xi*xi<=ni;xi++) {
// mi x = mi(xi);
// res += mi(sqrt(ni-1ll*xi*xi) + eps + 1) * n * (n+I1);
// for(int yi=0;yi<=sqrt(ni-1ll*xi*xi);yi++) {
// mi y = mi(yi);
// res += (p2(x)+p2(y)-p4(x)-p4(y)-I2*p2(x)*p2(y));
// }
// }
// res *= (n+I1) * inv2;
// for(int xi=1;1ll*xi*xi<=ni;xi++)
// for(int yi=0;yi<=sqrt(ni-1ll*xi*xi);yi++) {
// mi x = mi(xi), y = mi(yi);
// res += pw2sum[x*x+y*y-I1], res -= pw2sum[n];
// }
// Iter 9
// for(int xi=1;1ll*xi*xi<=ni;xi++) {
// mi x = mi(xi);
// res += mi(sqrt(ni-1ll*xi*xi) + eps + 1) * (p2(x) - p4(x) + n * (n+I1));
// for(int yi=0;yi<=sqrt(ni-1ll*xi*xi);yi++) {
// mi y = mi(yi);
// res += (p2(y)-p4(y));
// }
// mi tsum;
// for(int yi=0;yi<=sqrt(ni-1ll*xi*xi);yi++) {
// mi y = mi(yi);
// tsum += p2(y);
// }
// res += -I2*p2(x) * tsum;
// }
// res *= (n+I1) * inv2;
// for(int xi=1;1ll*xi*xi<=ni;xi++)
// for(int yi=0;yi<=sqrt(ni-1ll*xi*xi);yi++) {
// mi x = mi(xi), y = mi(yi);
// res += pw2sum[x*x+y*y-I1], res -= pw2sum[n];
// }
// Iter 10
// for(int xi=1;1ll*xi*xi<=ni;xi++) {
// mi x = mi(xi);
// res += mi(sqrt(ni-1ll*xi*xi) + eps + 1) * (p2(x) - p4(x) + n * (n+I1));
// res += pw2sum[sqrt(ni-1ll*xi*xi) + eps];
// for(int yi=0;yi<=sqrt(ni-1ll*xi*xi);yi++) {
// mi y = mi(yi);
// res += -p4(y);
// }
// mi tsum = pw2sum[sqrt(ni-1ll*xi*xi) + eps];
// res += -I2*p2(x) * tsum;
// }
// res *= (n+I1) * inv2;
// for(int xi=1;1ll*xi*xi<=ni;xi++)
// for(int yi=0;yi<=sqrt(ni-1ll*xi*xi);yi++) {
// mi x = mi(xi), y = mi(yi);
// res += pw2sum[x*x+y*y-I1], res -= pw2sum[n];
// }
// Iter 11
// for(int xi=1;1ll*xi*xi<=ni;xi++) {
// mi x = mi(xi);
// res += mi(sqrt(ni-1ll*xi*xi) + eps + 1) * (p2(x) - p4(x) + n * (n+I1));
// res += pw2sum[sqrt(ni-1ll*xi*xi) + eps];
// res -= pw4sum[int(sqrt(ni-1ll*xi*xi) + eps)];
// mi tsum = pw2sum[sqrt(ni-1ll*xi*xi) + eps];
// res += -I2*p2(x) * tsum;
// }
// res *= (n+I1) * inv2;
// for(int xi=1;1ll*xi*xi<=ni;xi++)
// for(int yi=0;yi<=sqrt(ni-1ll*xi*xi);yi++) {
// mi x = mi(xi), y = mi(yi);
// res += pw2sum[x*x+y*y-I1], res -= pw2sum[n];
// }
// Iter 12
// for(int xi=1;1ll*xi*xi<=ni;xi++) {
// mi x = mi(xi);
// res += mi(sqrt(ni-1ll*xi*xi) + eps + 1) * (p2(x) - p4(x) + n * (n+I1));
// res += pw2sum[sqrt(ni-1ll*xi*xi) + eps];
// res -= pw4sum[int(sqrt(ni-1ll*xi*xi) + eps)];
// mi tsum = pw2sum[sqrt(ni-1ll*xi*xi) + eps];
// res += -I2*p2(x) * tsum;
// }
// res *= (n+I1) * inv2;
// for(int xi=1;1ll*xi*xi<=ni;xi++) {
// res -= mi(sqrt(ni-1ll*xi*xi) + eps + 1) * pw2sum[n];
// for(int yi=0;yi<=sqrt(ni-1ll*xi*xi);yi++) {
// mi x = mi(xi), y = mi(yi);
// res += pw2sum[x*x+y*y-I1];
// }
// }
// Iter 13
// for(int xi=1;1ll*xi*xi<=ni;xi++) {
// mi x = mi(xi);
// res += mi(sqrt(ni-1ll*xi*xi) + eps + 1) * (p2(x) - p4(x) + n * (n+I1));
// res += pw2sum[sqrt(ni-1ll*xi*xi) + eps];
// res -= pw4sum[int(sqrt(ni-1ll*xi*xi) + eps)];
// mi tsum = pw2sum[sqrt(ni-1ll*xi*xi) + eps];
// res += -I2*p2(x) * tsum;
// }
// res *= (n+I1) * inv2;
// for(int xi=1;1ll*xi*xi<=ni;xi++)
// res -= mi(sqrt(ni-1ll*xi*xi) + eps + 1) * pw2sum[n];
// for(int xi=1;1ll*xi*xi<=ni;xi++) {
// for(int yi=0;yi<=sqrt(ni-1ll*xi*xi);yi++) {
// mi x = mi(xi), y = mi(yi);
// res += (x*x+y*y-I1)*(x*x+y*y)*(I2*x*x+I2*y*y-I1) * inv6;
// }
// }
// Iter 14
// for(int xi=1;1ll*xi*xi<=ni;xi++) {
// mi x = mi(xi);
// res += mi(sqrt(ni-1ll*xi*xi) + eps + 1) * (p2(x) - p4(x) + n * (n+I1));
// res += pw2sum[sqrt(ni-1ll*xi*xi) + eps];
// res -= pw4sum[int(sqrt(ni-1ll*xi*xi) + eps)];
// mi tsum = pw2sum[sqrt(ni-1ll*xi*xi) + eps];
// res += -I2*p2(x) * tsum;
// }
// res *= (n+I1) * inv2;
// for(int xi=1;1ll*xi*xi<=ni;xi++)
// res -= mi(sqrt(ni-1ll*xi*xi) + eps + 1) * pw2sum[n];
// for(int xi=1;1ll*xi*xi<=ni;xi++)
// for(int yi=0;yi<=sqrt(ni-1ll*xi*xi);yi++) {
// mi x = mi(xi), y = mi(yi);
// res += (p4(x)+p4(y)+I2*p2(x)*p2(y)-p2(x)-p2(y))*(I2*x*x+I2*y*y-I1) * inv6;
// }
// Iter 15
// for(int xi=1;1ll*xi*xi<=ni;xi++) {
// mi x = mi(xi);
// res += mi(sqrt(ni-1ll*xi*xi) + eps + 1) * (p2(x) - p4(x) + n * (n+I1));
// res += pw2sum[sqrt(ni-1ll*xi*xi) + eps];
// res -= pw4sum[int(sqrt(ni-1ll*xi*xi) + eps)];
// mi tsum = pw2sum[sqrt(ni-1ll*xi*xi) + eps];
// res += -I2*p2(x) * tsum;
// }
// res *= (n+I1) * inv2;
// for(int xi=1;1ll*xi*xi<=ni;xi++)
// res -= mi(sqrt(ni-1ll*xi*xi) + eps + 1) * pw2sum[n];
// mi tsum;
// for(int xi=1;1ll*xi*xi<=ni;xi++)
// for(int yi=0;yi<=sqrt(ni-1ll*xi*xi);yi++) {
// mi x = mi(xi), y = mi(yi);
// tsum += (I2*p6(x) + I2*p6(y)
// +I6*p2(x)*p4(y) + I6*p4(x)*p2(y)
// +p2(x)+p2(y)
// -I6*p2(x)*p2(y)
// -I3*p4(x)-I3*p4(y));
// }
// Iter 16
// for(int xi=1;1ll*xi*xi<=ni;xi++) {
// mi x = mi(xi);
// res += mi(sqrt(ni-1ll*xi*xi) + eps + 1) * (p2(x) - p4(x) + n * (n+I1));
// res += pw2sum[sqrt(ni-1ll*xi*xi) + eps];
// res -= pw4sum[int(sqrt(ni-1ll*xi*xi) + eps)];
// mi tsum = pw2sum[sqrt(ni-1ll*xi*xi) + eps];
// res += -I2*p2(x) * tsum;
// }
// res *= (n+I1) * inv2;
// for(int xi=1;1ll*xi*xi<=ni;xi++)
// res -= mi(sqrt(ni-1ll*xi*xi) + eps + 1) * pw2sum[n];
// mi tsum;
// for(int xi=1;1ll*xi*xi<=ni;xi++) {
// mi x = mi(xi);
// tsum += mi(sqrt(ni-1ll*xi*xi) + eps + 1) * (I2*p6(x) + p2(x));
// for(int yi=0;yi<=sqrt(ni-1ll*xi*xi);yi++) {
// mi y = mi(yi);
// tsum += (I2*p6(y)
// + I6*p2(x)*p4(y) + I6*p4(x)*p2(y)
// + p2(y)
// - I6*p2(x)*p2(y)
// - I3*p4(x)-I3*p4(y));
// }
// }
// Iter 17
for(int xi=1; 1ll*xi*xi<=ni; xi++) {
mi x = mi(xi);
res += mi(sqrt(ni-1ll*xi*xi) + eps + 1) * (p2(x) - p4(x) + n * (n+I1));
res += pw2sum[sqrt(ni-1ll*xi*xi) + eps];
res -= pw4sum[int(sqrt(ni-1ll*xi*xi) + eps)];
mi tsum = pw2sum[sqrt(ni-1ll*xi*xi) + eps];
res -= I2 * p2(x) * tsum;
}
res *= (n+I1) * inv2;
for(int xi=1;1ll*xi*xi<=ni;xi++)
res -= mi(sqrt(ni-1ll*xi*xi) + eps + 1) * pw2sum[n];
mi tsum;
for(int xi=1;1ll*xi*xi<=ni;xi++) {
mi x = mi(xi);
tsum += mi(sqrt(ni-1ll*xi*xi) + eps + 1) * (I2*p6(x) + p2(x) - I3*p4(x));
tsum -= I6 * p2(x) * pw2sum[sqrt(ni-1ll*xi*xi) + eps];
tsum += I6 * p2(x) * pw4sum[int(sqrt(ni-1ll*xi*xi) + eps)];
tsum += I2 * pw6sum[int(sqrt(ni-1ll*xi*xi) + eps)];
tsum += I6 * p4(x) * pw2sum[sqrt(ni-1ll*xi*xi) + eps];
tsum += pw2sum[sqrt(ni-1ll*xi*xi) + eps];
tsum -= I3 * pw4sum[int(sqrt(ni-1ll*xi*xi) + eps)];
}
//
res += tsum * inv6;
res = res * I4 + (n+I1) * (n+I1) * (n) * inv2 - pw2sum[n];
printf("%d", res.x);
return 0;
}