loj Snakes 的 Naïve Graph 【數論】
阿新 • • 發佈:2018-06-25
int mat bin con 表示 開始 res include ref
那麽首先在模\(a_i\)意義下分別有一個整環
我們把這些整環放在一起,用向量表示,成一個新環,可與模\(m\)意義下的整環一一對應,即環同構
例如\(Z/6 = Z/2 \centerdot Z/3\)
則對應關系
0 (0,0)
1 (1,1)
2 (0,2)
3 (1,0)
4 (0,1)
5 (1,2) 為\(m\)的倍數即可
對於\(p > 2\),\(p\)不能同時整除\((x + 1)\)和\((x - 1)\),所以只能一者為\(0\),所以有兩種方案
對於\(p = 2\),\((x + 1)(x - 1)\)必須都是偶數,顯然有一個不能整除\(4\),所以另一個應能整除\(2^{k-1}\),或者兩個如\(p > 2\)的情況,有一者為\(0\),但是\(k \le 2\)時會重復,所以特判一下,\(k = 1\)為\(1\),\(k = 2\)為\(2\),否則為\(4\)
以上線篩處理即可
題目鏈接
loj
題解
感謝珂神的指導orz
觀察式子\(i \times j \equiv 1 \pmod m\),顯然\(i,j\)是模\(m\)意義下成對的逆元,只需統計模\(m\)意義下存在逆元的數的個數,即與\(m\)互質的數的個數\(\varphi(m)\)
每對逆元的連邊有兩種情況,記逆元對數為\(x\),則方案數為\(2^x\)
真的完了嗎?難點才剛開始
模\(m\)意義下有的數逆元為本身!此時不能計入答案
所以我們還需求模\(m\)意義下逆元為本身的數的個數
重新理解一下中國剩余定理,本質是環同構
令\(m = a_1a_2a_3\dots\)
其中\(a_i = p_i^{k_i}\)
那麽首先在模\(a_i\)意義下分別有一個整環
我們把這些整環放在一起,用向量表示,成一個新環,可與模\(m\)意義下的整環一一對應,即環同構
例如\(Z/6 = Z/2 \centerdot Z/3\)
則對應關系
0 (0,0)
1 (1,1)
2 (0,2)
3 (1,0)
4 (0,1)
5 (1,2)
環同樣滿足加減乘
所以我們需要求出在模每個\(a_i\)下平方等於\(1\)的數的個數,乘起來即可
\[
\begin{aligned}
x^2 \equiv 1 \pmod m \(x + 1)(x - 1) \equiv 0 \pmod m
\end{aligned}
\]
所以我們只需\((x + 1)(x - 1)\)
對於\(p > 2\),\(p\)不能同時整除\((x + 1)\)和\((x - 1)\),所以只能一者為\(0\),所以有兩種方案
對於\(p = 2\),\((x + 1)(x - 1)\)必須都是偶數,顯然有一個不能整除\(4\),所以另一個應能整除\(2^{k-1}\),或者兩個如\(p > 2\)的情況,有一者為\(0\),但是\(k \le 2\)時會重復,所以特判一下,\(k = 1\)為\(1\),\(k = 2\)為\(2\),否則為\(4\)
以上線篩處理即可
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define mp(a,b) make_pair<int,int>(a,b)
#define cls(s) memset(s,0,sizeof(s))
#define cp pair<int,int>
#define LL long long int
#define res register
using namespace std;
const int maxn = 10000005,maxm = 100005,INF = 1000000000,P = 311021;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == ‘-‘) flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
int p[maxn],pi,isn[maxn],phi[maxn],N = 10000000;
int f[maxn],bin[maxn],tw[maxn],tot[maxn],all[maxn];
void init(){
phi[1] = 1;
for (res int i = 2; i <= N; i++){
if (!isn[i]){
p[++pi] = i,phi[i] = i - 1;
if (i == 2) tw[i] = 1;
else tot[i] = 1;
}
for (res int j = 1; j <= pi && i * p[j] <= N; j++){
isn[i * p[j]] = true;
if (i % p[j] == 0){
phi[i * p[j]] = phi[i] * p[j];
if (p[j] == 2){
tw[i * p[j]] = tw[i] + 1;
tot[i * p[j]] = tot[i];
}
else{
tw[i * p[j]] = tw[i];
tot[i * p[j]] = tot[i];
}
break;
}
phi[i * p[j]] = phi[i] * (p[j] - 1);
if (p[j] == 2){
tot[i * p[j]] = tot[i];
tw[i * p[j]] = tw[i] + 1;
}
else{
tot[i * p[j]] = tot[i] + 1;
tw[i * p[j]] = tw[i];
}
}
}
bin[0] = 1;
for (res int i = 1; i <= N; i++)
bin[i] = (bin[i - 1] << 1),bin[i] >= P ? (bin[i] -= P) : 0;
for (res int i = 1; i <= N; i++){
all[i] = bin[tot[i]];
if (tw[i] == 2) all[i] = all[i] * 2 % P;
else if (tw[i] > 2) all[i] = all[i] * 4 % P;
}
for (res int i = 1; i <= N; i++){
f[i] = f[i - 1] + bin[(phi[i] - all[i]) >> 1],f[i] >= P ? (f[i] -= P) : 0;
}
}
int c[maxn],ci;
int main(){
init();
int q = read(),l,r;
while (q--){
l = read(); r = read();
printf("%d\n",(f[r] - f[l - 1] + P) % P);
}
return 0;
}
loj Snakes 的 Naïve Graph 【數論】