4815: [Cqoi2017] Tabular Mobius inversion of small Q block

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 }
View Code

 

The feelings of the past Beyond the memory Past thoughts Inscriptions
Inscriptions The regrets
left in the childhood Inscription and pride






Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324989241&siteId=291194637