The topic of international practice:
Seeing these two formulas, many people will think that it is related to gcd. Yes, the final conclusion is f(a,b)=f(gcd(a,b))*(a/gcd(a,b))*(b/gcd(a,b)). However, the conclusion can only be guessed, we consider how to prove it.
The structural proofs of many great gods on the Internet are very clear, but I am too naive to construct them, so let's send a non-structural proof.
Code (senior players have been unafraid of card constants):
1 #include<cstdio> 2 #include<algorithm> 3 #include<cmath> 4 #define bool unsigned char 5 #define debug cout 6 typedef long long int lli; 7 const int maxn=4e6+1e2,maxb=2e3+1e2; 8 const int mod=1e9+7; 9 10 lli phi[maxn]; 11 int n,m; 12 13 inline lli fastpow(lli base,int tim) { 14 lli ret = 1; base %= mod; 15 while(tim) { 16 if( tim & 1 ) ret = ret * base % mod; 17 if( tim >>= 1 ) base = base * base % mod; 18 } 19 return ret; 20 } 21 inline int gcd(int x,int y) { 22 register int t; 23 while( ( t = x % y ) ) x = y , y = t; 24 return y; 25 } 26 27 namespace Pre { 28 inline void sieve() { 29 static int prime[maxn],cnt; 30 static bool vis[maxn]; 31 phi[1] = 1; 32 for(int i=2;i<=n;i++) { 33 if( !vis[i] ) prime[++cnt] = i , phi[i] = i - 1; 34 for(int j=1;j<=cnt&&(lli)i*prime[j]<=n;j++) { 35 const int tar = i * prime[j]; 36 vis[tar] = 1; 37 if( i % prime[j] ) phi[tar] = phi[i] * ( prime[j] - 1 ); 38 else { 39 phi[tar] = phi[i] * prime[j]; 40 break; 41 } 42 } 43 } 44 for(int i=1;i<=n;i++) phi[i] = ( phi[i] * i % mod * i % mod + phi[i-1] ) % mod; 45 } 46 } 47 48 struct BlockedArrary { 49 lli dat[maxn],sumins[maxn],blk[maxb],sumblk[maxb]; 50 int bel[maxn],st[maxb],ed[maxb],blksiz,cnt; 51 52 inline lli query(int pos) { 53 return pos ? ( sumblk[bel[pos]-1] + sumins[pos] ) % mod : 0; 54 } 55 inline void update(int pos,lli val) { 56 dat[pos] = val; 57 int id = bel[pos] , l = st[id] , r = ed[id]; 58 sumins[l] = dat[l]; for(int i=std::max(pos,l+1);i<=r;i++) sumins[i] = ( sumins[i-1] + dat[i] ) % mod; 59 blk[id] = sumins[r]; for(int i=id;i<=cnt;i++) sumblk[i] = ( sumblk[i-1] + blk[i] ) % mod; 60 } 61 inline void init() { 62 for(int i=1;i<=n;i++) dat[i] = (lli) i * i % mod; 63 blksiz = std::sqrt(n); 64 for(int l=1,r;l<=n;l=r+1) { 65 r = std::min( l + blksiz - 1 , n ) , ++cnt , st[cnt] = l , ed[cnt] = r , sumins[l] = dat[l]; 66 for(int i=l;i<=r;i++) bel[i] = cnt; 67 for(int i=l+1;i<=r;i++) sumins[i] = ( sumins[i-1] + dat[i] ) % mod; 68 sumblk[cnt] = ( sumblk[cnt-1] + (blk [cnt] = sumins [r]))% mod; 69 } 70 } 71 } ba; 72 73 inline void update ( int a, int b, lli d) { 74 int g = gcd (a, b); 75 lli tv = d% mod * fastpow ((lli) a * b / g / g, mod- 2 )% mod; 76 ba.update (g, tv); 77 } 78 79 inline lli query ( int k) { 80 lli ret = 0 ; 81 for ( int i =1,j;i<=k;i=j+1) { 82 j = k / ( k / i ); 83 ret = ( ret + ( ba.query(j) - ba.query(i-1) + mod ) % mod * phi[k/i] % mod ) % mod; 84 } 85 return ret; 86 } 87 88 int main() { 89 static int a,b,k; 90 static lli x; 91 scanf("%d%d",&m,&n) , Pre::sieve() , ba.init(); 92 while(m--) scanf("%d%d%lld%d",&a,&b,&x,&k) , update(a,b,x) , printf("%lld\n",query(k)); 93 return 0; 94 }
The feelings of the past Beyond the memory Past thoughts Inscriptions
Inscriptions The regrets
left in the childhood Inscription and pride