題目鏈結
給定 \(n\),求:首先,這個求和範圍有些不爽,利用對稱性轉化一下得:\[f(n)=\sum_^n\sum_^i\frac(i,j)}\bmod (10^9 + 7)
\]\(1\le n\le 10^9\)
\[f(n)=\frac 12\left(n+\sum_^n\sum_^n\frac(i,j)}\right)
\]然後推一下式子:
\[\begin
\sum_^n\sum_^n\frac(i,j)}=&\sum_^n\sum_^n\frac\\
=&\sum_\sum_^\sum_^ij[\gcd(i,j)=1]\\
=&\sum_\sum_\mu(e)e^2\sum_^\rfloor}\sum_^\rfloor}ij\\
=&\sum_\left(\sum_\mu(e)e^2\right)\left(\frac2\right)^2
\end
\]於是問題轉化為對 \(f(n)=\sum_\mu(d)d^2\) 求字首和。
對於數論函式 \(a,b\),完全積性函式\(c\),有:證明:把式子化開:\[(a\cdot c)*(b\cdot c)=(a*b)\cdot c
\]
\[\sum_a(d)c(d)b(\frac nd)c(\frac nd)=c(n)\sum_a(d)b(\frac nd)
\]回到 \(f(n)\)。顯然有 \(f=(\mu \cdot \text_2)*1\)。考慮杜教篩。兩邊同時卷上乙個 \(\text_2\):
\[\begin
(\mu\cdot \text_2)*1*\text_2=&(\mu\cdot\text_2)*(1\cdot\text_2)*1\\
=&(\mu*1)\cdot \text_2*1\\
=&\epsilon *1\\
=&1\end
\]於是可以杜教篩。注意到計算式子需要的字首和全都可以表示為前 \(\lfloor\frac nd\rfloor\) 項的和,記憶化一下即可。
record & code:
#include #include typedef long long ll;
const ll p = 1e9 + 7,inv2 = (p + 1) / 2,inv3 = (p + 1) / 3;
const int n = 5e5,maxn = n + 5;
ll n,lst,ans;
ll pri[maxn]; bool isp[maxn];
ll mu[maxn],pre[maxn];
std::map < ll,ll > mem;
inline ll read()
inline ll get1(ll n)
inline ll get2(ll n)
inline void init()
}for(ll t,i = 1;i <= n;i ++)
for(ll i = 1;i <= n;i ++) pre[i] = (pre[i] + pre[i - 1]) % p;
}inline ll getsum(ll n)
return mem[n] = (res - cur + p) % p;
}int main()
printf("%lld\n",(ans + n) * inv2 % p);
return 0;
}
LibreOJ 6177 題解(狀壓DP)
傳送門 剛看到這道題時想的是跟最短哈密頓路類似的二進位制狀壓dp,先用floyd處理距離 但是此題用二進位制不夠,應該用三進製 0,1,2分別表示未送,正在送,已送完 dp s i 表示當前送到任務狀態為s,現在在點i 狀態轉移方程見 時間複雜度 o n 3 3 qqn include includ...
題解 LibreOJ6277 數列分塊入門 1
更好的閱讀體驗 portal1 libreoj 給出乙個長為 n 的數列,以及 n 個操作,操作涉及區間加法,單點查值。第一行輸入乙個數字 n 第二行輸入 n 個數字,第 i 個數字為 a i 以空格隔開。接下來輸入 n 行詢問,每行輸入四個數字 opt l r c 以空格隔開。若 texttt 表...
LibreOJ6279 數列分塊入門 3 題解
題目描述 給出乙個長為 n 的數列,以及 n 個操作,操作涉及區間加法,詢問區間內小於某個值 x 的前驅 比其小的最大元素 輸入格式 第一行輸入乙個數字 n 第二行輸入 n 個數字,第 i 個數字為 a i 以空格隔開。接下來輸入 n 行詢問,每行輸入四個數字 opt l r c 以空格隔開。若 o...