详见dalao的《洪华敦-类欧几里得算法》
这个算法的来源,可以形象化的理解为欧几里得算法的几何意义。
图详见上面的PPT。
对于一个平面,每个整点有一个价值,
如果需要求一条直线与坐标轴围成的部分的整点价值和,
设这条直线为 y = a x + b y=ax+b y=ax+b,那么可以通过PPT中的方法不断更换坐标轴递归求解。
推式子很烦。
但还是要推。
1.求 F ( a , b , c , n ) = ∑ i = 0 n ⌊ a i + b c ⌋ F(a,b,c,n) = \sum_{i=0}^n \lfloor\frac {ai+b}{c}\rfloor F(a,b,c,n)=∑i=0n⌊cai+b⌋
F ( a , b , c , n ) = ∑ i = 0 n ⌊ ( a m o d    c ) i + ( b m o d    c ) c ⌋ + i ⌊ a c ⌋ + ⌊ b c ⌋ F(a,b,c,n) = \sum_{i=0}^n \lfloor\frac {(a\mod c)i+(b\mod c)}c\rfloor + i\lfloor\frac ac\rfloor+\lfloor\frac bc\rfloor F(a,b,c,n)=∑i=0n⌊c(amodc)i+(bmodc)⌋+i⌊ca⌋+⌊cb⌋
设 ⌊ ( a m o d    c ) n + ( b m o d    c ) c ⌋ = M \lfloor\frac {(a\mod c)n+(b\mod c)}c\rfloor = M ⌊c(amodc)n+(bmodc)⌋=M
S n k = ∑ i = 0 n i k S_n^k = \sum_{i=0}^n i^k Snk=∑i=0nik
F ( a , b , c , n ) = S n 1 ⌊ a c ⌋ + S n 0 ⌊ b c ⌋ + ∑ i = 0 n ⌊ ( a m o d    c ) i + ( b m o d    c ) c ⌋ = S n 1 ⌊ a c ⌋ + S n 0 ⌊ b c ⌋ + ∑ j = 0 M − 1 ∑ i = 0 n [ j < ⌊ ( a m o d    c ) i + ( b m o d    c ) c ⌋ ] = S n 1 ⌊ a c ⌋ + S n 0 ⌊ b c ⌋ + ∑ j = 0 M − 1 ∑ i = 0 n 1 − [ j > = ⌊ ( a m o d    c ) i + ( b m o d    c ) c ⌋ ] = S n 1 ⌊ a c ⌋ + S n 0 ⌊ b c ⌋ + ( n + 1 ) M − ∑ j = 0 M − 1 ∑ i = 0 n [ j + 1 > ⌊ ( a m o d    c ) i + ( b m o d    c ) c ⌋ ] = S n 1 ⌊ a c ⌋ + S n 0 ⌊ b c ⌋ + ( n + 1 ) M − ∑ j = 0 M − 1 ∑ i = 0 n [ i ( a m o d    c ) < ( j + 1 ) c − ( b m o d    c ) ] = S n 1 ⌊ a c ⌋ + S n 0 ⌊ b c ⌋ + ( n + 1 ) M − ∑ j = 0 M − 1 ∑ i = 0 n [ i ( a m o d    c ) < = ( j + 1 ) c − ( b m o d    c ) − 1 ] = S n 1 ⌊ a c ⌋ + S n 0 ⌊ b c ⌋ + ( n + 1 ) M − ∑ j = 0 M − 1 ∑ i = 0 n [ i < = ⌊ ( j + 1 ) c − ( b m o d    c ) − 1 a m o d    c ⌋ ] = S n 1 ⌊ a c ⌋ + S n 0 ⌊ b c ⌋ + ( n + 1 ) M − ∑ j = 0 M − 1 ∑ i = 0 n [ i < = ⌊ j c + c − ( b m o d    c ) − 1 a m o d    c ⌋ = S n 1 ⌊ a c ⌋ + S n 0 ⌊ b c ⌋ + ( n + 1 ) M − F ( c , c − ( b m o d    c ) − 1 , a m o d    c , M − 1 ) − M = S n 1 ⌊ a c ⌋ + S n 0 ⌊ b c ⌋ + n M − F ( c , c − ( b m o d    c ) − 1 , a m o d    c , M − 1 ) F(a,b,c,n) = S_n^1\lfloor\frac ac\rfloor + S_n^0\lfloor \frac bc\rfloor + \sum_{i=0}^n \lfloor\frac {(a\mod c)i+(b\mod c)}c\rfloor\\ =S_n^1\lfloor\frac ac\rfloor + S_n^0\lfloor \frac bc\rfloor + \sum_{j=0}^{M-1} \sum_{i=0}^n[j< \lfloor\frac {(a\mod c)i+(b\mod c)}c\rfloor]\\ =S_n^1\lfloor\frac ac\rfloor + S_n^0\lfloor \frac bc\rfloor + \sum_{j=0}^{M-1} \sum_{i=0}^n1-[j>= \lfloor\frac {(a\mod c)i+(b\mod c)}c\rfloor]\\ =S_n^1\lfloor\frac ac\rfloor + S_n^0\lfloor \frac bc\rfloor + (n+1)M-\sum_{j=0}^{M-1} \sum_{i=0}^n[j+1> \lfloor\frac {(a\mod c)i+(b\mod c)}c\rfloor]\\ =S_n^1\lfloor\frac ac\rfloor + S_n^0\lfloor \frac bc\rfloor + (n+1)M-\sum_{j=0}^{M-1} \sum_{i=0}^n[i(a\mod c)<(j+1)c-(b\mod c)]\\ =S_n^1\lfloor\frac ac\rfloor + S_n^0\lfloor \frac bc\rfloor + (n+1)M-\sum_{j=0}^{M-1} \sum_{i=0}^n[i(a\mod c)<=(j+1)c-(b\mod c)-1]\\ =S_n^1\lfloor\frac ac\rfloor + S_n^0\lfloor \frac bc\rfloor + (n+1)M-\sum_{j=0}^{M-1} \sum_{i=0}^n[i<=\lfloor\frac {(j+1)c-(b\mod c)-1}{a\mod c}\rfloor]\\ =S_n^1\lfloor\frac ac\rfloor + S_n^0\lfloor \frac bc\rfloor + (n+1)M-\sum_{j=0}^{M-1} \sum_{i=0}^n[i<=\lfloor\frac {jc+c-(b\mod c)-1}{a\mod c}\rfloor\\ =S_n^1\lfloor\frac ac\rfloor + S_n^0\lfloor \frac bc\rfloor + (n+1)M-F(c,c-(b\mod c)-1,a\mod c,M-1)-M\\ =S_n^1\lfloor\frac ac\rfloor + S_n^0\lfloor \frac bc\rfloor + nM-F(c,c-(b\mod c)-1,a\mod c,M-1) F(a,b,c,n)=Sn1⌊ca⌋+Sn0⌊cb⌋+i=0∑n⌊c(amodc)i+(bmodc)⌋=Sn1⌊ca⌋+Sn0⌊cb⌋+j=0∑M−1i=0∑n[j<⌊c(amodc)i+(bmodc)⌋]=Sn1⌊ca⌋+Sn0⌊cb⌋+j=0∑M−1i=0∑n1−[j>=⌊c(amodc)i+(bmodc)⌋]=Sn1⌊ca⌋+Sn0⌊cb⌋+(n+1)M−j=0∑M−1i=0∑n[j+1>⌊c(amodc)i+(bmodc)⌋]=Sn1⌊ca⌋+Sn0⌊cb⌋+(n+1)M−j=0∑M−1i=0∑n[i(amodc)<(j+1)c−(bmodc)]=Sn1⌊ca⌋+Sn0⌊cb⌋+(n+1)M−j=0∑M−1i=0∑n[i(amodc)<=(j+1)c−(bmodc)−1]=Sn1⌊ca⌋+Sn0⌊cb⌋+(n+1)M−j=0∑M−1i=0∑n[i<=⌊amodc(j+1)c−(bmodc)−1⌋]=Sn1⌊ca⌋+Sn0⌊cb⌋+(n+1)M−j=0∑M−1i=0∑n[i<=⌊amodcjc+c−(bmodc)−1⌋=Sn1⌊ca⌋+Sn0⌊cb⌋+(n+1)M−F(c,c−(bmodc)−1,amodc,M−1)−M=Sn1⌊ca⌋+Sn0⌊cb⌋+nM−F(c,c−(bmodc)−1,amodc,M−1)
高斯函数与整数大于小于号化简技巧:
x < a x<a x<a即 x + 1 < = a x+1<=a x+1<=a
a b < x ab<x ab<x即 a < ⌈ x b ⌉ a<\lceil \frac xb \rceil a<⌈bx⌉很明显这对于我们下取整更加流行的趋势不利,所以可以这样
a b < = x ab<=x ab<=x即 a < = ⌊ x b ⌋ a<=\lfloor \frac xb\rfloor a<=⌊bx⌋
a b < x ab<x ab<x即 a < = ⌊ x − 1 b ⌋ a<=\lfloor \frac {x-1}b \rfloor a<=⌊bx−1⌋
这样也比较好反着推回去。
整除函数推式子,和数论函数推式子差不多恶心吧,
杜教洲阁,欧几里得。
例题:
求 ∑ k = 0 n ( ( k m ) a n d m ) ( m o d 1 e 9 + 7 ) \sum_{k=0}^n ((km)\ and \ m)\pmod {1e9+7} ∑k=0n((km) and m)(mod1e9+7)
其中 a n d and and为按位与, m < = 1 e 11 , n < = 1 e 18 m<=1e11,n<=1e18 m<=1e11,n<=1e18
按位计算,求有多少个 k k k使得 ( k m ) a n d m (km)\ and \ m (km) and m在第 i i i位为1.
那么这个可以转化为等差数列除 2 i 2^i 2i之和,
就是经典的类欧几里得算法了。
AC Code:
#include
#define maxn 100005
#define mod 1000000007
#define LL long long
using namespace std;
int F(LL a,LL b,LL c,LL n){
int N = n % mod;
LL m = ((__int128)(a % c) * n + (b % c)) / c;
LL ret = (1ll * N * (N+1) / 2 % mod * (a / c % mod) + 1ll * (N+1) * (b / c % mod)) % mod;
if(a % c == 0) return ret;
return (ret + 1ll * N * (m % mod) - F(c,c-(b%c)-1,a%c,m-1)) % mod;
}
LL n,m;
int main(){
scanf("%lld%lld",&n,&m);
int ans = 0;
for(int i=0;i<=60;i++)
if(m>>i&1){
int c = (F(m,0,1ll<<i,n) - 2ll * F(m,0,2ll<<i,n)) % mod;
ans = (ans + 1ll * c * ((1ll<<i) % mod)) % mod;
}
printf("%d\n",(ans+mod)%mod);
}