解题报告: HDU_4675 GCD of Sequence 计数
来源:互联网 发布:贵阳大数据是什么 编辑:程序博客网 时间:2024/04/30 17:36
题目链接
题意:
给定长度为n的一个正整数序列,里面每个数的大小均为最大为m,让你构造出另一个等长的正整数序列要求满足一下三个条件:
1、数列里的每个数小于等于m。
2、整个数列的最大公因子为d。
3、你构造出的数列与原数列对应位置上的数刚好有k对不相等。
询问你当d 分别为 1~m 时,能构造出序列的种类数。
思路:
不好直接考虑计算最大公因子刚好为d的结果(设为f(d)),那么先计算最大公因子为d的倍数的结果(设为g(d)),那么可知,,其中u(i) 为反演系数,那么已知g函数的结果,我们就能在O(mlog(n))的时间求得答案。
条件三可以理解为从原数列中选k个数改变。
那么就有n-k个数的值不发生改变,如果这n-k个数中存在不是d的倍数的数,那么就无法得到要求的数列,此时结果为0。
设原数列中有x个数为d的倍数,那么:
① n-k > x :
说明不变的数中一定有数不是d的倍数,此时结果为0
g[d] = 0
② n-k <= x :
对于 (n-k) 个不是d的倍数的数 ,这些数一定要改变成小于等于m的d的倍数,它们有m/d中选择。
对于 剩下的 j = ( x - (n-k) )个原本就是d的倍数的数,这些数的选择有 C(x,j) 种,它们要变成除了它们自己以外的其余(m/d - 1)个数之一。
g[d] = pow(m/d , n-k ) * C(x,j) * pow(m/d -1 , j );
即可。
#include<bits/stdc++.h>#define pii pair<int,int>#define fi first#define se secondconst int mod = 1e9+7;using namespace std;int n,m,k;int A[300005];int mu[300005];int pr[33000];long long ni[300005];long long fac[300006];int isp[300005];int num[300005];long long ans[300005];vector<pii>V;vector<int>E[300005];long long qpow(long long x,int y){ long long res = 1; while(y){ if(y&1)res = res * x % mod; y>>=1; x = x * x % mod ; }return res;}void init(){ fac[0] = ni[0] = 1; for(int i=1;i<=3e5;i++){ isp[i]=true; fac[i] =(1LL*fac[i-1]*i%mod); ni[i] = qpow(fac[i],mod-2); for(int j=i;j<=3e5;j+=i){ E[j].emplace_back(i); } } mu[1]=1; int all = 0; for(int i=2;i<=3e5;i++){ if(isp[i]){ mu[i] = -1; pr[all++] = i; }for(int j=0;j<all;j++){ long long t = 1LL * pr[j] * i; if(t>3e5)break; mu[t] = -mu[i]; isp[t] = false; if(i%pr[j]==0){ mu[t] = 0; break; } }if(mu[i]){ V.emplace_back(pii(i,mu[i])); } }}inline long long C(int n,int m){ if(n==m||m==0)return 1LL; return 1LL*fac[n]*ni[n-m]%mod*ni[m]%mod;}int main(){ init(); while(scanf("%d%d%d",&n,&m,&k)==3){ memset(num,0,sizeof(num)); for(int i=1;i<=n;i++){ scanf("%d",&A[i]); for(int j=0;j<E[A[i]].size();j++){ num[E[A[i]][j]]++; } }for(int i=1;i<=m;i++){ int cnt = m/i , j = k+num[i]-n; if(n-num[i]<=k)ans[i] = 1LL * qpow(cnt,n-num[i]) * C(num[i],j) % mod * qpow(cnt-1,j) % mod; else ans[i] = 0; }for(int i=1;i<=m;i++){ for(int j=0;j<V.size();j++){ int t = V[j].fi * i ; if(t<=m){ ans[i] = ( ans[i] + V[j].se * ans[t] + mod )% mod ; }else { break; } }printf("%I64d%c",ans[i],i<m?' ':'\n'); } }return 0;}
阅读全文
0 0
- 解题报告: HDU_4675 GCD of Sequence 计数
- HDU4675-GCD of Sequence(数论+组合计数)
- hdu 4675 GCD of Sequence(计数)
- HDOJ-5019-Revenge of GCD 解题报告
- [Baltic2014]sequence 解题报告
- [SDOI2016]sequence 解题报告
- HDU4675 GCD of Sequence
- hdu 5726 GCD 解题报告
- PKU 3581 Sequence 解题报告
- 1141 Brackets Sequence 解题报告
- 【POJ2442】Sequence 解题报告+代码
- HDU 4675 GCD of Sequence
- HDU 4675 GCD of Sequence
- 【九度OJ】题目1442:A sequence of numbers 解题报告
- Uva 1640(计数) 解题报告
- 解题报告:HDU_6035 Colorful Tree 树上计数
- 解题报告:HDU_6122 Color the chessboard (计数)
- 杭电“GCD Again ”解题报告
- MATLAB函数编程(持续添加)
- pytorch 若干小坑
- vTaskSuspendAll和xTaskResumeAll
- 基础知识记录:Fragment生命周期
- 8、Oracle:group by用法
- 解题报告: HDU_4675 GCD of Sequence 计数
- 014-情绪|第一生产力
- STL常用函数复习之————list
- 华为上机编程之字符串中含有该字符的个数
- Amateras Modeler
- Android设置顶部状态栏的颜色
- 正六边形
- 同步请求和异步请求以及多次点击
- Centos修改yum源