hdu 6053

题意:给出长度为n的A数列,问是否存在一个b数列,1<=bi<=ai,对于B数列的任意区间的gcd都>=2;

思路:枚举每一个gcd(2--100000),然后将其分成长度为gcd的段,如当前gcd为3,我们可以分为0-2,3-5,6-8....,对于第一段如果存在的话,就代表组成不了gcd为3的了,第二段可以组成gcd为3的,第3段可以组成gcd为3,为6,所以num[i]里面有gcd为i,2*i,3*i....的所有总和,最后去个重,

PS:我徐巨巨还是强的呀

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const ll mod=1e9+7;
 5 const int N=1e5+10;
 6
 7 ll a[N],sum[N];
 8 ll num[N],dp[N];
 9
10 ll hh(ll x,ll y){
11     ll s=1;
12     while(y){
13         if(y&1) s=s*x%mod;
14         x=x*x%mod;
15         y/=2;
16     }
17     return s;
18 }
19
20 int main(){
21     int t;
22     int k=1;
23     scanf("%d",&t);
24     while(t--){
25         int n;
26         memset(a,0,sizeof(a));
27         memset(sum,0,sizeof(sum));
28         memset(num,0,sizeof(num));
29         scanf("%d",&n);
30         ll x;
31         for(int i=1;i<=n;i++){
32             scanf("%d",&x);a[x]++;
33         }
34         for(int i=1;i<=100020;i++)
35             sum[i]=sum[i-1]+a[i];
36         ll s;
37         for(int i=2;i<=100000;i++){
38             num[i]=1;
39             for(int j=0;j<=100000;j+=i){//j为当前段的起点//
40                 if(j+i-1>100000) s=sum[100000]-sum[j-1];//s为这一段的个数//
41                 else if(j==0) s=sum[j+i-1];
42                 else s=sum[j+i-1]-sum[j-1];
43                 ll yueshu=j/i;
44                 if(yueshu==0&&s) num[i]=0;
45                 if(s)num[i]=num[i]*hh(yueshu,s)%mod;
46             }
47         }
48         for(int i=100000;i>=2;i--){
49             dp[i]=num[i];
50             for(int j=i+i;j<=100000;j+=i){
51                 dp[i]=(dp[i]-dp[j]+mod)%mod;
52             }
53         }
54         ll ssum=0;
55         for(int i=2;i<=100000;i++){
56              ssum=(ssum+dp[i]+mod)%mod;
57         }
58         printf("Case #%d: %I64d\n",k++,ssum);
59     }
60     return 0;
61 }
时间: 2024-10-20 11:06:48

hdu 6053的相关文章

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 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 [题目大意] 给出一个数列每个位置可以取到的最大值, 问这个可以构造多少个数列,使得他们的最大公约数大于1 [题解] 我们可以枚举最大公约数k,对于k来说, 他对答案的贡献为∏[ai/k],我们将数列中的数字转化为权值数组 ∏_{i=1}^{100000}[i/k],对于求解i/k的部分我们可以进行数值分块, j*k-1~j*k+k-1的数值除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 (莫比乌斯)

题意:给你一个序列a,求序列b满足 ①1<=bi<=ai ②对于序列b[l,r] gcd(bl,...,br)>=2的序列数是多少 思路:显然这道需要我们枚举gcd 设F(d)是序列b满足gcd是d的倍数的个数 F(d)的结果显而易见为∏a[i]/d 根据容斥原理ans=F(2)+F(3)+F(5)-F(6)+F(7)-F(10)..... 根据莫比乌斯,我们可以把它写成ans=∑d-u(d)∏a[i]/d log(n^2)的时间复杂度太高,我们需要进行分块处理 设f(i,d)是数组a中

hdu 6053 TrickGCD 筛法

TrickGCD Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) 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

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

HDU 6203 ping ping ping [LCA,贪心,DFS序,BIT(树状数组)]

题目链接:[http://acm.hdu.edu.cn/showproblem.php?pid=6203] 题意 :给出一棵树,如果(a,b)路径上有坏点,那么(a,b)之间不联通,给出一些不联通的点对,然后判断最少有多少个坏点. 题解 :求每个点对的LCA,然后根据LCA的深度排序.从LCA最深的点对开始,如果a或者b点已经有点被标记了,那么continue,否者标记(a,b)LCA的子树每个顶点加1. #include<Bits/stdc++.h> using namespace std;

HDU 5542 The Battle of Chibi dp+树状数组

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5542 题意:给你n个数,求其中上升子序列长度为m的个数 可以考虑用dp[i][j]表示以a[i]结尾的长度为j的上升子序列有多少 裸的dp是o(n2m) 所以需要优化 我们可以发现dp的第3维是找比它小的数,那么就可以用树状数组来找 这样就可以降低复杂度 #include<iostream> #include<cstdio> #include<cstring> #include