zoj3868
来源:互联网 发布:淘宝卖家真实姓名隐藏 编辑:程序博客网 时间:2024/06/07 18:53
/*** 题目:I.GCD Expectation 链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5480 题意:给定一个可以重复的集合,对于所有非空的子集,计算其gcd的k次方的和模998244353(题意理解之后就是这样的意思),sum{gcd(ai,aj……)^k}%998244353; 思路:从大到小枚举可能的gcd,假如我们枚举到了i,那么集合里面类似i,2*i,3*i,4*i这样的数存在的话都是可以统计进来的。 假如这样的数是num,那么可能的集合个数就是2^num-1,然后减去gcd不是i的就是gcd是i的个数了,不是i的记录在dp数组里面,详见代码!复杂度O(Nlog(N)),其中N=max{ai} 代码:***/#include<map>#include<queue>#include<cmath>#include<cstdio>#include<vector>#include<cstring>#include <iostream>#include<algorithm>using namespace std;const int N=2000010;const long long MOD=998244353;long long dp[N],vis[N];int n,k,a[N];long long q_pow(long long x,int y){ long long res=1; while(y>0){ if(y&1)res=(res*x)%MOD; y>>=1; x=(x*x)%MOD; } return res;}int main(){ int T; scanf("%d",&T); while(T--){ scanf("%d%d",&n,&k); int maxn=0; for(int i=0;i<n;i++){ scanf("%d",&a[i]); maxn=max(maxn,a[i]); } long long res=0; for(int i=0;i<=maxn;i++) vis[i]=dp[i]=0;///初始化 for(int i=0;i<n;i++) vis[a[i]]++;///记录个数 for(int i=maxn;i>=1;i--){ int num=vis[i];///这里初始化成vis[i]可以应对给定的集合是重复的 long long sum=0; for(int j=i+i;j<=maxn;j+=i){ sum=(sum+dp[j])%MOD;///最大公约数都不是i的集合个数,且组成这个集合的元素是i的倍数 num+=vis[j]; } long long now=q_pow(2,num)-1;///非空的集合个数 ///减去那些最大公约数不是i的个数sum,然后剩下最大公约数是i的个数dp[i] dp[i]=((now-sum)%MOD+MOD)%MOD; res=(res+q_pow(i,k)*dp[i])%MOD;///gcd的k次方乘以个数 } cout<<res<<endl; } return 0;}
0 0
- zoj3868
- ZOJ3868:GCD Expectation
- 欢迎使用CSDN-markdown编辑器
- 写博文的理由.
- hdu1071数学题 The area
- KVM VM硬盘满的解决方案
- KVM 镜像快照的创建
- zoj3868
- ntdll.dll和ntoskrnl.exe中的NT*和ZW*函数区别
- nginx 实现Web应用程序的负载均衡
- graph-tool的编译安装
- 黑马程序员——OC内存管理
- pat中文练习简单题1002. 写出这个数
- VC驿站《VC++实战HTTP之POST》教程
- Socket网络通信理论基础搜集(TCP/IP协议栈与数据包封装+TCP与UDP的区别)
- 命题逻辑等值演算