首页 > 其他 > 详细

【SDOI2017】数字表格 [莫比乌斯反演]

时间:2017-04-12 03:42:51      阅读:448      评论:0      收藏:0      [点我收藏+]

数字表格

Time Limit: 50 Sec  Memory Limit: 128 MB
[Submit][Status][Discuss]

Description

  Doris刚刚学习了fibonacci数列。用f[i]表示数列的第i项,那么
  f[0]=0
  f[1]=1
  f[n]=f[n-1]+f[n-2],n>=2
  Doris用老师的超级计算机生成了一个n×m的表格,第i行第j列的格子中的数是f[gcd(i,j)],其中gcd(i,j)表示i,j的最大公约数。Doris的表格中共有n×m个数,她想知道这些数的乘积是多少。答案对10^9+7取模。

Input

  第一个一个数T,表示数据组数。
  接下来T行,每行两个数n,m

Output

  输出T行,第i行的数是第i组数据的结果

Sample Input

  3
  2 3
  4 5
  6 7

Sample Output

  1
  6
  960

HINT

  T<=1000,1<=n,m<=10^6

Solution

  运用莫比乌斯反演,得到式子:

技术分享

  这样我们对于内外分块即可,复杂度为O(n^(0.75)T)。

  在SDOI配置机上可以过,BZOJ上死活卡不过去QAQ。

Code

技术分享
  1 #include<iostream>  
  2 #include<string>  
  3 #include<algorithm>  
  4 #include<cstdio>  
  5 #include<cstring>  
  6 #include<cstdlib>  
  7 #include<cmath>
  8 using namespace std; 
  9 typedef long long s64;
 10 
 11 const int ONE = 1e6+2;
 12 const int MOD = 1e9+7;
 13 const int PHI = 1e9+6;
 14 
 15 int T;
 16 int n,m;
 17 int prime[ONE],p_num,miu[ONE];
 18 int Niyu[ONE];
 19 int F[ONE];
 20 bool isp[ONE];
 21 int Ans;
 22 
 23 namespace input
 24 {
 25         const int BufferSize = 1 << 16 | 1;
 26         
 27         char buffer[BufferSize];
 28         char *head = buffer + BufferSize;
 29         const char *tail = head;
 30         
 31         inline char nextChar()
 32         {
 33             if (head == tail)
 34             {
 35                 fread(buffer, 1, BufferSize, stdin);
 36                 head = buffer;
 37             }
 38             return *head++;
 39         }
 40         
 41         inline int get()
 42         {
 43             static char c;
 44             while ((c = nextChar()) < 0 || c > 9);
 45         
 46             int res = c - 0;
 47             while ((c = nextChar()) >= 0 && c <= 9)
 48                 res = res * 10 + c - 0;
 49             return res;
 50         }
 51 }
 52 using input::get;
 53 
 54 inline int Quickpow(int a,int b)
 55 {
 56         int res = 1;
 57         while(b)
 58         {
 59             if(b&1) res = (s64)res*a%MOD;
 60             a = (s64)a*a%MOD;
 61             b>>=1;
 62         }
 63         return res;
 64 }
 65 
 66 inline void Deal_first(int MaxN)
 67 {
 68         F[0]=0;    F[1]=1;
 69         int val=1;
 70         for(int i=2; i<=MaxN; i++)
 71         {
 72             F[i] = F[i-1]+F[i-2];
 73             if(F[i] >= MOD) F[i] -= MOD;
 74             val=(s64)val*F[i]%MOD;
 75         }
 76         Niyu[MaxN] = Quickpow(val, MOD-2);
 77         for(int i=MaxN-1;i>=1;i--) Niyu[i] = (s64)Niyu[i+1] * F[i+1] % MOD;
 78         Niyu[0] = Niyu[1]; F[0]=1;
 79         for(int i=1; i<=MaxN; i++) F[i] = (s64)F[i]*F[i-1] % MOD;
 80         
 81         miu[1] = 1;
 82         for(int i=2; i<=MaxN; i++)
 83         {
 84             if(!isp[i])
 85                 prime[++p_num] = i, miu[i] = -1;
 86             for(int j=1; j<=p_num, i*prime[j]<=MaxN; j++)
 87             {
 88                 isp[i * prime[j]] = 1;
 89                 if(i % prime[j] == 0)
 90                 {
 91                     miu[i * prime[j]] = 0;
 92                     break;
 93                 }
 94                 miu[i * prime[j]] = -miu[i];
 95             }
 96             miu[i] += miu[i-1];
 97         }
 98 }
 99 
100 inline int f(int n,int m)
101 {
102         if(n > m) swap(n,m);
103         int Ans = 0;
104         for(int i=1,j=0; i<=n; i=j+1)
105         {
106             int x=n/i, y=m/i;
107             j = min(n/x, m/y);
108             Ans = ((s64)Ans + (s64)x * y%PHI * ((s64)miu[j] - miu[i-1] + PHI) )%PHI;
109         }
110         return Ans;
111 }
112 
113 inline void Solve()
114 {
115         n=get();    m=get();
116         if(n > m) swap(n,m);
117         Ans = 1;
118         for(int i=1,j=0; i<=n; i=j+1)
119         {
120             int x=n/i, y=m/i;
121             j = min(n/x, m/y);
122             Ans = (s64)Ans * Quickpow( (s64)F[j] * Niyu[i-1] % MOD , f(x,y) ) % MOD;
123         }
124         printf("%d\n",Ans);
125 }
126 
127 int main()
128 {
129         Deal_first(ONE-1);
130         T = get();
131         while(T--)
132             Solve();
133         return 0;
134 }
View Code

 

  

【SDOI2017】数字表格 [莫比乌斯反演]

原文:http://www.cnblogs.com/BearChild/p/6696543.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!