HDU 6169 Senior PanⅡ(数论+dp)
2018-02-12 13:21
295 查看
Description
给出一个区间[L,R][L,R],问该区间中所有以KK作为最小因子(大于11的)的数字之和
Input
第一行输入一整数TT表示用例组数,每组用例输入三个整数L,R,KL,R,K(1≤L≤R≤1011,2≤K≤1011)(1≤L≤R≤1011,2≤K≤1011)
Output
对于每组用例,输出答案,结果模109+7109+7
Sample Input
2
1 20 5
2 6 3
Sample Output
Case #1: 5
Case #2: 3
Solution
显然kk需要是素数,否则不存在数字以KK为最小因子,且如果KK是NN的因子,那么N/KN/K也是NN的因子,进而有K≤N/KK≤N/K,故K≤N−−√K≤N,即如果K>1011−−−−√≈320000K>1011≈320000时,至多有一个数字(即KK本身)以KK为最小因子,当K≤320000K≤320000时,只需解决11~NN中以KK为最小素因子的数字之和即可
考虑dpdp,以dp[i][j]dp[i][j]表示前ii个数字中没有以前jj个素数为最小素因子的数字之和,假设KK是第pos+1pos+1个因子,如果一个数字XX以KK为最小素因子,那么X/KX/K必然不以前pospos个素数为最小素因子,反之,如果YY不以前pospos个素因子为最小素因子,则YKYK必然以KK为最小素因子,那么我们只要求11~⌊NK⌋⌊NK⌋中没有以前pospos个素数为最小素因子的数字之和,乘上KK即为11~NN中以KK为最小素因子的数字之和,且同理可以得到转移方程,前ii个数字中不以前jj个素数为最小素因子的数字之和==前ii个数字中不以前j−1j−1个素数为最小素因子的数字之和−−前ii个数字中以第jj个素数为最小素因子的数字之和,即dp[i][j]=dp[i][j−1]−pj⋅dp[⌊ipj⌋][j−1]dp[i][j]=dp[i][j−1]−pj⋅dp[⌊ipj⌋][j−1]
Code
给出一个区间[L,R][L,R],问该区间中所有以KK作为最小因子(大于11的)的数字之和
Input
第一行输入一整数TT表示用例组数,每组用例输入三个整数L,R,KL,R,K(1≤L≤R≤1011,2≤K≤1011)(1≤L≤R≤1011,2≤K≤1011)
Output
对于每组用例,输出答案,结果模109+7109+7
Sample Input
2
1 20 5
2 6 3
Sample Output
Case #1: 5
Case #2: 3
Solution
显然kk需要是素数,否则不存在数字以KK为最小因子,且如果KK是NN的因子,那么N/KN/K也是NN的因子,进而有K≤N/KK≤N/K,故K≤N−−√K≤N,即如果K>1011−−−−√≈320000K>1011≈320000时,至多有一个数字(即KK本身)以KK为最小因子,当K≤320000K≤320000时,只需解决11~NN中以KK为最小素因子的数字之和即可
考虑dpdp,以dp[i][j]dp[i][j]表示前ii个数字中没有以前jj个素数为最小素因子的数字之和,假设KK是第pos+1pos+1个因子,如果一个数字XX以KK为最小素因子,那么X/KX/K必然不以前pospos个素数为最小素因子,反之,如果YY不以前pospos个素因子为最小素因子,则YKYK必然以KK为最小素因子,那么我们只要求11~⌊NK⌋⌊NK⌋中没有以前pospos个素数为最小素因子的数字之和,乘上KK即为11~NN中以KK为最小素因子的数字之和,且同理可以得到转移方程,前ii个数字中不以前jj个素数为最小素因子的数字之和==前ii个数字中不以前j−1j−1个素数为最小素因子的数字之和−−前ii个数字中以第jj个素数为最小素因子的数字之和,即dp[i][j]=dp[i][j−1]−pj⋅dp[⌊ipj⌋][j−1]dp[i][j]=dp[i][j−1]−pj⋅dp[⌊ipj⌋][j−1]
Code
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<cmath> #include<vector> #include<queue> #include<map> #include<set> #include<ctime> using namespace std; typedef long long ll; #define M 320000 #define mod 1000000007 #define inv2 500000004 #define A 8000 #define B 1000 int res=0,p[M+5],mark[M+5],dp[A+5][B+5]; int ins(int x,int y) { return x+y>=mod?x+y-mod:x+y; } int des(int x,int y) { return x-y<0?x-y+mod:x-y; } void init() { for(int i=2;i<=M;i++) if(!mark[i]) { p[++res]=i; for(int j=2*i;j<=M;j+=i)mark[j]=1; } dp[0][0]=0; for(int i=1;i<=A;i++) { dp[i][0]=ins(dp[i-1][0],i); for(int j=1;j<=B;j++) dp[i][j]=des(dp[i][j-1],(ll)p[j]*dp[i/p[j]][j-1]%mod); } } bool check(ll n) { if(n<=M)return mark ^1; for(int i=1;i<=res&&(ll)p[i]*p[i]<=n;i++) if(n%p[i]==0)return 0; return 1; } int Solve(ll n,int m) { if(n<2)return n; if(m==0) { n%=mod; return n*(n+1)%mod*inv2%mod; } if(n<=A&&m<=B)return dp [m]; if(n<=p[m])return 1; return des(Solve(n,m-1),(ll)p[m]*Solve(n/p[m],m-1)%mod); } int main() { init(); int T,Case=1; scanf("%d",&T); while(T--) { ll L,R,K; scanf("%I64d%I64d%I64d",&L,&R,&K); printf("Case #%d: ",Case++); if(!check(K))printf("0\n"); else if(K>M) { if(K>=L&&K<=R)printf("%d\n",K%mod); else printf("0\n"); } else { int pos=1; while(p[pos]<K)pos++; pos--; int ans=des(K*Solve(R/K,pos)%mod,K*Solve((L-1)/K,pos)%mod); printf("%d\n",ans); } } return 0; }
相关文章推荐
- HDU 6169 Senior PanⅡ 数论+DP
- HDU 6169(数论+DP)
- HDU - 6169 Senior PanⅡ(dp+数论)
- hdu 6169 DP
- HDU 6125 Free from square(数论+状压DP)
- hdu 6169 DP
- hdu 6169 DP
- hdu 6169 DP
- hdu 6169 DP
- hdu 3944 DP? 组合数学与数论的结合
- 2017多校第9场 HDU 6169 Senior PanⅡ 数论,DP,爆搜
- 解题报告:HDU_3944 DP? 数论
- HDU 5656 CA Loves GCD (数论DP)
- 解题报告:HDU_6169 Senior PanⅡ (记忆化搜索)
- hdu 4345 Permutation(数论+dp)
- hdu 6169 DP
- hdu 4345 Permutation 【数论+dp】
- HDU 1133 (数论 or DP、高精度;Java版)
- hdu 6169 DP
- hdu 6169 DP