[bzoj4314] 倍数?倍数! 解题报告
来源:互联网 发布:mac 播放器 字幕 编辑:程序博客网 时间:2024/04/28 05:41
感觉完全不会做。。看讨论区里有大爷用母函数做的。。完全不会母函数,所以想看看官方题解。。但是官方题解要登录topcoder,注册还得翻墙,然后还是英文,搞了好久终于看懂了。感觉每一步都非常神。。
我们要求的是集合的个数,集合是无序的,这并不好求。我们可以变无序为有序,先求有序集合的数量然后除以k!。
考虑一个元素互不相同的长为k-1的序列,如果说我们要求长为k的序列mod n=0的话,实际上最后一个元素就已经被确定了。所以我们就可以写出:长为k的序列所有元素互不相同和mod n=0的序列方案数=长为k-1的序列所有元素互不相同的序列方案数-长为k的序列有且仅有一对元素相同且mod n=0的方案数。
但问题是,后者依然不易求。不过,按照类似的思路,我们考虑一下有且仅有一对元素相同且mod n=0的序列,我们把这一对元素放到最后,设前k-2个元素的和为S,则最后一对元素就是S+2x=0 mod n的解。这就是一个经典的丢番图方程问题了。显然,当且仅当(2,n)|S时有解,且解有(2,n)个,所以问题就被神奇的化归到了mod (2,n)=0时的情况!
所以我们可以设f(k,d,a)表示在[0,n)中选k个不同的数构成序列,要求它们mod d=0,且最后一个数在序列的最后重复了a遍的方案数。考虑转移,前k-1个数的和为S,则S+ax=0 mod d当且仅当S mod (a,d)=0,且x的循环节长度是
再考虑一下边界情况,当k=1时,答案当然就是
所以总的转移就是
时间复杂度是
不过注意到实际上这个上界是很松的,因为光a、k这两维实际上就应该是
但是空间呢?注意到实际上我们只需要保存
#include<cstdio>#include<iostream>using namespace std;#include<algorithm>#include<cstring>const int Mod=1000000007;typedef long long LL;const int N=1e9+5,K=1000+5;LL pow(LL prod,int x){ LL ans=1; for(;x;x>>=1){ if(x&1)ans=ans*prod%Mod; prod=prod*prod%Mod; } return ans;}int gcd[K][K],gn[K];int n;LL f[K][K];LL array[K];LL dfs(int k,int d,int a){ int g=d==n?gn[a]:gcd[a][d]; if(k==1)return n/d*g; if(d==1)return array[k]; if(a==1&&d<=1000){ if(f[k][d]==-1)f[k][d]=((n/d*g*dfs(k-1,g,1)-(k-1)*dfs(k-1,d,a+1))%Mod+Mod)%Mod; //printf("f(%d,%d,%d)=%I64d\n",k,d,a,f[k][d]); return f[k][d]; } LL ans=((n/d*g*dfs(k-1,g,1)-(k-1)*dfs(k-1,d,a+1))%Mod+Mod)%Mod; //printf("f(%d,%d,%d)=%I64d\n",k,d,a,ans); //cout<<n/d*g*dfs(k-1,g,1)<<endl; return ans;}int main(){ int k; scanf("%d%d",&n,&k); if(n<k){ puts("0"); return 0; } for(int i=1;i<=k;++i){ gcd[i][0]=gcd[0][i]=i; for(int j=1;j<=i;++j)gcd[i][j]=gcd[j][i]=gcd[i%j][j]; gn[i]=gcd[i][n%i]; } array[0]=1; for(int i=1;i<=k;++i)array[i]=array[i-1]*(n-i+1)%Mod; memset(f,-1,sizeof(f)); LL ans=dfs(k,n,1); //7cout<<ans<<endl; for(int i=k;i;--i)ans=ans*pow(i,Mod-2)%Mod; cout<<ans<<endl;}
总结:
①无序与有序之间的相互转化经常非常有用!
②dp时如果感觉状态不够用可以尝试大胆的扩展。
- [bzoj4314] 倍数?倍数! 解题报告
- 一中OJ #3509 七的倍数 [USACO Jan16,洛谷P3131] | 同余前缀和 | 解题报告
- 找倍数
- 约数倍数
- 找倍数
- 找倍数
- 找倍数
- 最小倍数
- 寻找倍数
- 寻找倍数
- bzoj 4314: 倍数?倍数! 数学
- 3的倍数和5的倍数
- 国际度量倍数单位
- 14的倍数
- 最大公约数,最小共倍数
- X倍数问题
- 多网店下修改价格倍数
- 凸透镜的放大倍数
- 一个古老的汇编框架
- windows10相关文章
- 组合组件のCusRelativeLayout(Android-自定义相对布局)
- 【SSH】Spring:从Demo看IOC基本原理
- 2016武汉科技大学邀请赛现场赛 C题
- [bzoj4314] 倍数?倍数! 解题报告
- BitmapFactory.Options
- Android开发の实用Api与数据结构
- LeetCode-131.Palindrome Partitioning
- Java开发中的23种设计模式详解(转)
- MySQL Load data
- Webview图片上传方法
- HDU 5681:zxa and wifi
- 第一次写java后台的感觉