HDU 6053 ( TrickGCD ) 分块+容斥

TrickGCD

Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 3401    Accepted Submission(s): 1268

Problem Description

You are given an array A , and Zhu wants to know there are how many different array B satisfy the following conditions?

* 1≤Bi≤Ai
* For each pair( l , r ) (1≤l≤r≤n) , gcd(bl,bl+1...br)≥2

Input

The first line is an integer T(1≤T≤10) describe the number of test cases.

Each test case begins with an integer number n describe the size of array A.

Then a line contains n numbers describe each element of A

You can assume that 1≤n,Ai≤105

Output

For the kth test case , first output "Case #k: " , then output an integer as answer in a single line . because the answer may be large , so you are only need to output answer mod 109+7

Sample Input

1
4
4 4 4 4

Sample Output

Case #1: 17

Source

2017 Multi-University Training Contest - Team 2

思路:枚举gcd ,对于当前的i,分区间地计算出gcd为i倍数的数列总数,之后利用容斥来减掉重复的部分,要保证每次减掉都是确定的倍数因此要倒着减。

代码:

 1 #include<bits/stdc++.h>
 2 #define db double
 3 #define ll long long
 4 #define ci(x) scanf("%d",&x)
 5 #define cd(x) scanf("%lf",&x)
 6 #define cl(x) scanf("%lld",&x)
 7 #define pi(x) printf("%d\n",x)
 8 #define pd(x) printf("%f\n",x)
 9 #define pl(x) printf("%lld\n",x)
10 #define fr(i,a,b) for(int i=a;i<=b;i++)
11 using namespace std;
12 const int N=1e5+5;
13 const int mod=1e9+7;
14 const int MOD=mod-1;
15 const db  eps=1e-10;
16 const int inf = 0x3f3f3f3f;
17 ll a[N];
18 ll sum[N];
19 ll qpow(ll x,ll n)
20 {
21     ll ans=1;x%=mod;
22     for(;n>0;n>>=1){if(n&1) ans=(ans*x)%mod;x=x*x%mod;}
23     return ans;
24 }
25 int main()
26 {
27 //    ios::sync_with_stdio(false);
28 //    cin.tie(0);
29     int t;
30     ci(t);
31     for(int ii=1;ii<=t;ii++)
32     {
33         int n,x,ma=-N,mi=N;
34         memset(sum,0,sizeof(sum));
35         ci(n);
36         for(int i=0;i<n;i++)
37             ci(x),sum[x]++,ma=max(ma,x),mi=min(mi,x);
38         for(int i=1;i<=ma;i++) sum[i]+=sum[i-1];//统计小于等于i的数字的个数
39         for(int i=2;i<=mi;i++){//从2~mi枚举gcd
40             a[i]=1;
41             for(int j=i;j<=ma;j+=i){//分区间计算
42                 int c;
43                 if(i+j-1<=ma) c=sum[i+j-1]-sum[j-1];
44                 else c=sum[ma]-sum[j-1];
45                 if(!c) continue;
46                 a[i]=(a[i]*qpow(j/i,c))%mod;
47             }
48         }
49         ll ans=0;
50         for(int i=mi;i>=2;i--)
51         {
52             for(int j=i+i;j<=mi;j+=i) a[i]=(a[i]-a[j])%mod;//减掉确定的倍数
53             a[i]=(a[i]+mod)%mod;
54             ans=(ans+a[i])%mod;
55         }
56         printf("Case #%d: %lld\n",ii,ans);
57     }
58 }
时间: 2024-10-10 06:43:32

HDU 6053 ( TrickGCD ) 分块+容斥的相关文章

HDU 6053 TrickGCD 莫比乌斯函数/容斥/筛法

题意:给出n个数$a[i]$,每个数可以变成不大于它的数,现问所有数的gcd大于1的方案数.其中$(n,a[i]<=1e5)$ 思路:鉴于a[i]不大,可以想到枚举gcd的值.考虑一个$gcd(a_1,a_2,a_3…a_n)=d$,显然每个$a_i$的倍数都满足,有$\frac{a_i}{d}$种方案 那么一个d对答案的贡献为\[\prod_{i=1}^{min(a)}{\lfloor\frac{a_i}{d}\rfloor}    \] 但是所有的d计入会有重复情况,考虑容斥,对d进行素数分

HDU 5213 分块 容斥

给出n个数,给出m个询问,询问 区间[l,r] [u,v],在两个区间内分别取一个数,两个的和为k的对数数量. $k<=2*N$,$n <= 30000$ 发现可以容斥简化一个询问.一个询问的答案为 $[l,v]+(r,u)-[l,u)-(r,v]$,那么我们离线询问,将一个询问分成四个,分块暴力就行了. 然后就是注意细节,不要发生越界,访问错位置之类比较蠢的问题了. /** @Date : 2017-09-24 19:54:55 * @FileName: HDU 5213 分块 容斥.cpp

HDU 6053 - TrickGCD

/* HDU 6053 - TrickGCD [ 莫比乌斯函数,筛法分块 ] 题意: 给出数列 A[N],问满足: 1 <= B[i] <= A[i] ; 对任意(l, r) (1<=l<=r<=n) ,使得 gcd(bl,...br) >= 2 ; 的 B[N] 数列的个数 分析: 设 gcd(b1,...bn) = k (k >= 2),此时 k 对答案的贡献为 (a1/k)*(a2/k)*(a3/k)*...*(an/k) 根据容斥原理,ans = +[k=

HDU 6053 TrickGCD 容斥

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=6053 题意: 给你序列a,让你构造序列b,要求 1<=b[i]<=a[i],且b序列的gcd>=2.问你方案数. 思路: 容易想到的就是我们枚举整个序列的gcd,然后a[i]/gcd就是i位置能够填的数的个数,然后每个位置累积就能得到数列为gcd时的方案数. 最后容斥一下累加就是答案.但是最大gcd可以是100000和明显这样做n^2,会超时. 那么我们把a[i]/gcd的放在一起,然后用

HDU 6053 TrickGCD(分块)

[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=6053 [题目大意] 给出一个数列每个位置可以取到的最大值, 问这个可以构造多少个数列,使得他们的最大公约数大于1 [题解] 我们可以枚举最大公约数k,对于k来说, 他对答案的贡献为∏[ai/k],我们将数列中的数字转化为权值数组 ∏_{i=1}^{100000}[i/k],对于求解i/k的部分我们可以进行数值分块, j*k-1~j*k+k-1的数值除k得到的结果都是相同的,因此可以直接求这个结果

JZYZOJ1518 [haoi2011]b 莫比乌斯反演 分块 容斥

http://172.20.6.3/Problem_Show.asp?id=1518最开始只想到了n^2的写法,肯定要超时的,所以要对求gcd的过程进行优化.首先是前缀和容斥,很好理解.第二个优化大致如下:u为莫比乌斯函数,t为gcd(x,y)为i的倍数的数的个数:满足gcd(x,y)=1的数字对的数量=sigma(1<=i<=min(x,y))u[i]*t[i];t[i]=(x/i)*(y-i);由小数向下取整可知有连续的i满足x/i为定值,y/i也是定值,所以可以分块计算,用u[i]的前缀

HDU 5321 Beautiful Set 容斥 (看题解)

HDU 5321 感觉有点抗拒这种题目, 看到就感觉自己不会写,其实就是个沙雕题, 感觉得找个时间练练这种题. g[ i ] 表示gcd为 i 的倍数的方案数, f[ i ] 表示gcd为 i 的方案数, 然后先算g[ i ]然后直接容斥. #pragma GCC optimize(2) #pragma GCC optimize(3) #include<bits/stdc++.h> #define LL long long #define LD long double #define ull

HDU 4135 Co-prime(容斥+数论)

Co-prime Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5526    Accepted Submission(s): 2209 Problem Description Given a number N, you are asked to count the number of integers between A and B

HDU 5297 Y sequence 容斥/迭代

Y sequence Problem Description Yellowstar likes integers so much that he listed all positive integers in ascending order,but he hates those numbers which can be written as a^b (a, b are positive integers,2<=b<=r),so he removed them all.Yellowstar ca