题解 数
补题使我快乐
将 \(a, b, c\) 均用 \(b\) 表示
变形得 \(k=b(3b-4a)\)
感觉打表发现结论的概率比推出来大(雾
那么令
\(G_k(n)=\sum\limits_{i=2}^n[i\equiv 1\pmod 4\and(\operatorname{low}(i)>p_k\or \operatorname{ispri}(i))]\)
\(G'_k(n)=\sum\limits_{i=2}^n[i\equiv 3\pmod 4\and(\operatorname{low}(i)>p_k\or \operatorname{ispri}(i))]\)
Min_25 筛,两者互相转移即可
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 5000010
#define fir first
#define sec second
#define pb push_back
#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 ll read() {
ll ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
ll n;
namespace force{
int ans;
vector<pair<int, int>> buc[N];
ll qval(int a, int d) {return 2*a*d+3*d*d-a*a;}
void solve() {
for (int d=1; d<=n; ++d)
for (int a=1; a<=2*d||qval(a, d)>0; ++a)
if (qval(a, d)<=n) {
// assert(qval(a, d)>=max(a, d));
buc[qval(a, d)].pb({a, d});
}
// for (int i=1; i<=1000; ++i) if (buc[i].size()) {
// cout<<i<<": "; for (auto it:buc[i]) cout<<"("<<it.fir<<','<<it.sec<<") "; cout<<endl;
// }
for (int i=1; i<=n; ++i) if (buc[i].size()==1) ++ans;
cout<<ans<<endl;
}
}
namespace task1{
bool npri[N];
int pri[N], pcnt, ans;
void solve() {
for (int i=2; i<=n; ++i) {
if (!npri[i]) pri[++pcnt]=i;
for (int j=1; j<=pcnt&&i*pri[j]<=n; ++j) {
npri[i*pri[j]]=1;
if (!(i%pri[j])) break;
}
}
if (n>=4) ++ans;
if (n>=16) ++ans;
for (int i=1; i<=pcnt; ++i) {
if (pri[i]%4==3) ++ans;
if (pri[i]!=2 && pri[i]*4<=n) ++ans;
if (pri[i]!=2 && pri[i]*16<=n) ++ans;
}
cout<<ans<<endl;
}
}
namespace liner_sieve{
bool npri[N];
int pri[N], pcnt;
void solve() {
ll ans=0;
for (int i=2; i<=n; ++i) {
if (!npri[i]) pri[++pcnt]=i, ans+=(i%4==3);
for (int j=1; j<=pcnt&&i*pri[j]<=n; ++j) {
npri[i*pri[j]]=1;
if (!(i%pri[j])) break;
}
}
cout<<ans<<endl;
}
}
namespace task{
bool npri[N];
int pri[N], pcnt;
ll id1[N], id2[N], g1[N], g2[N], sp1[N], sp2[N], uni[N], sqr, tot, ans;
void solve(ll n) {
sqr=sqrt(n); pcnt=tot=0;
for (int i=2; i<=sqr; ++i) {
if (!npri[i]) pri[++pcnt]=i, sp1[pcnt]=sp1[pcnt-1]+(i%4==1), sp2[pcnt]=sp2[pcnt-1]+(i%4==3);
for (int j=1; j<=pcnt&&i*pri[j]<=sqr; ++j) {
npri[i*pri[j]]=1;
if (!(i%pri[j])) break;
}
}
// memset(g1, 0, sizeof(g1));
// memset(g2, 0, sizeof(g2));
for (ll l=1,r; l<=n; l=r+1) {
r=n/(n/l);
ll t=n/l;
uni[++tot]=t;
if (t<=sqr) id1[t]=tot;
else id2[n/t]=tot;
g1[tot]=t/4+(t%4>=1)-1;
g2[tot]=t/4+(t%4>=3);
// for (int i=2; i<=t; ++i)
// if (i%4==1) ++g1[tot];
// else if (i%4==3) ++g2[tot];
// cout<<"t: "<<t<<endl;
// cout<<"g: "<<g1[tot]<<' '<<g2[tot]<<endl;
}
for (int i=1; i<=pcnt; ++i) {
for (int j=1; j<=tot&&1ll*pri[i]*pri[i]<=uni[j]; ++j) {
ll k=uni[j]/pri[i] <= sqr ? id1[uni[j]/pri[i]] : id2[n/(uni[j]/pri[i])];
g1[j]=(g1[j]-(pri[i]%4==1)*(g1[k]-sp1[i-1])-(pri[i]%4==3)*(g2[k]-sp2[i-1]));
g2[j]=(g2[j]-(pri[i]%4==1)*(g2[k]-sp2[i-1])-(pri[i]%4==3)*(g1[k]-sp1[i-1]));
}
}
// cout<<"g1: "; for (int i=1; i<=tot; ++i) cout<<g1[i]<<' '; cout<<endl;
// cout<<"g2: "; for (int i=1; i<=tot; ++i) cout<<g2[i]<<' '; cout<<endl;
}
void solve() {
solve(n);
ans+=g2[id2[1]];
solve(n/4);
ans+=g1[id2[1]]+g2[id2[1]];
solve(n/16);
ans+=g1[id2[1]]+g2[id2[1]];
if (n>=4) ++ans;
if (n>=16) ++ans;
cout<<ans<<endl;
}
}
signed main()
{
freopen("number.in", "r", stdin);
freopen("number.out", "w", stdout);
n=read();
// force::solve();
// task1::solve();
task::solve();
return 0;
}