题意:
用一句话表达就是,所有子区间上 不同质因数的 个数
思路:
质因数分解不用说,记下每个质因数的贡献位置(在哪个地方出现的),每次都加上包含这一点的区间减掉和之前最近的同一质因数重合的部分(贡献就是这些)。
代码:
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 vector <long long> ve[1000005]; 6 7 void add(long long pos, long long x) 8 { 9 long long i; 10 for(i=2;i*i<=x;i++) //t 11 { 12 if(x%i==0) 13 { 14 ve[i].push_back(pos); 15 while(x%i==0) 16 { 17 x /= i; 18 } 19 } 20 } 21 if(x>1) ve[x].push_back(pos); 22 } 23 24 int main() 25 { 26 long long n, i, j, x; 27 long long sum; 28 29 for(i=0;i<1000002;i++) 30 { 31 ve[i].push_back(0); 32 } 33 34 scanf("%lld", &n); 35 for(i=1;i<=n;i++) 36 { 37 scanf("%lld", &x); 38 add(i, x); 39 } 40 sum = 0; 41 for(i=2;i<1000002;i++) 42 { 43 for(j=1; j<ve[i].size(); j++) 44 { 45 sum += (ve[i][j] - ve[i][j-1]) * (n - ve[i][j] + 1); 46 } 47 } 48 printf("%lld", sum); 49 return 0; 50 }
有一说一,这题T了一晚上,原因是add里循环条件一开始用了sqrt()这个函数,服气!
分解质因数是这样:
1 #include <stdio.h> 2 #include <string.h> 3 4 int main() 5 { 6 int n, top, i; 7 int re[100005]; 8 scanf("%d", &n); 9 top = 0; 10 for(i=2;i*i<=n;i++) 11 { 12 if(n%i==0) 13 { 14 re[top++] = i; 15 while(n%i==0) 16 { 17 n /= i; 18 } 19 } 20 } 21 if(n>1) re[top++] = n; 22 printf("top = %d\n", top); 23 for(i=0;i<top;i++) 24 { 25 if(i==top-1) printf("%d\n", re[i]); 26 else printf("%d ", re[i]); 27 } 28 return 0; 29 }
这道题可用线性筛优化,只跑素数
代码:
1 #include <bits/stdc++.h> 2 #define maxn 1e6+2 3 using namespace std; 4 5 vector <long long> ve[1000005]; 6 long long top; 7 long long IsPrime[1000005], prime[100005]; 8 9 void init() 10 { 11 long long i; 12 for(i=0;i<maxn;i++) 13 { 14 ve[i].push_back(0); 15 } 16 } 17 18 void GetPrime() 19 { 20 long long i, j; 21 top = 0; 22 memset(IsPrime, 0, sizeof(IsPrime)); 23 IsPrime[0] = 1; 24 IsPrime[1] = 1; 25 for(i=2;i<maxn;i++) 26 { 27 if(IsPrime[i]==0) prime[top++] = i; 28 for(j=0;j<top&&i*prime[j]<maxn;j++) 29 { 30 IsPrime[i*prime[j]] = 1; 31 if(i%prime[j]==0) break; 32 } 33 } 34 } 35 36 void add(long long pos, long long x) 37 { 38 long long i; 39 for(i=0;i<top&&prime[i]*prime[i]<=x;i++) 40 { 41 if(x%prime[i]==0) 42 { 43 ve[prime[i]].push_back(pos); 44 while(x%prime[i]==0) 45 { 46 x /= prime[i]; 47 } 48 } 49 } 50 if(x>1) ve[x].push_back(pos); 51 } 52 53 int main() 54 { 55 long long n, i, j, x; 56 long long sum; 57 58 init(); 59 GetPrime(); 60 61 scanf("%lld", &n); 62 for(i=1;i<=n;i++) 63 { 64 scanf("%lld", &x); 65 add(i, x); 66 } 67 sum = 0; 68 for(i=2;i<maxn;i++) 69 { 70 for(j=1; j<ve[i].size(); j++) 71 { 72 sum = sum + (ve[i][j] - ve[i][j-1]) * (n - ve[i][j] + 1); 73 } 74 } 75 printf("%lld", sum); 76 return 0; 77 }