nssl1176-轨道【数论,Dp】
正題
題目大意
給出n,m,kn,m,kn,m,k
v=∏i=1nai(ai∈N+,ai<=m)k(gcd(v,k)=1)v=\frac{\prod_{i=1}^na_i(a_i\in N_+,a_i<=m)}{k}(gcd(v,k)=1)v=k∏i=1n?ai?(ai?∈N+?,ai?<=m)?(gcd(v,k)=1)
求aaa的方案個(gè)數(shù)mod10007mod\ 10007mod?10007的值
解題思路
fi,jf_{i,j}fi,j?表示前i個(gè)數(shù)的乘積和k的最大公約數(shù)為k的第j個(gè)約數(shù)時(shí)的方案個(gè)數(shù)。
動(dòng)態(tài)轉(zhuǎn)移方程:
fi,j=∑k=1prcj%prck=0fi?1,k?f1,prcnprcj/prckf_{i,j}=\sum_{k=1}^{prc_j\%prc_k=0}f_{i-1,k}*f_{1,prcn_{prc_j/prc_k}}fi,j?=k=1∑prcj?%prck?=0?fi?1,k??f1,prcnprcj?/prck???
prciprc_iprci?為k的第i個(gè)約數(shù),prcniprcn_iprcni?為i是k的第幾個(gè)約數(shù)。
然后我們考慮如何求出1~m1\sim m1~m內(nèi)有多少個(gè)數(shù)與k的最大公約數(shù)為k的第i個(gè)約數(shù)
也就是∑i=1m(gcd(i,k)==d)(d∣n)\sum_{i=1}^m (gcd(i,k)==d)(d|n)∑i=1m?(gcd(i,k)==d)(d∣n)
首先
gcd(i,k)=d?gcd(i/d,k)=1gcd(i,k)=d\Rightarrow gcd(i/d,k)=1gcd(i,k)=d?gcd(i/d,k)=1(數(shù)論基礎(chǔ))
我們可以考慮用容斥,我們將重復(fù)偶數(shù)次的減去,重復(fù)奇數(shù)次的加上。
之后預(yù)處理一下prcimodprcj==0prc_i\ \ mod\ \ prc_j==0prci???mod??prcj?==0的情況就好了。
code
#pragma GCC optimize(2) %:pragma GCC optimize(3) %:pragma GCC optimize("Ofast") %:pragma GCC optimize("inline") %:pragma GCC optimize("-fgcse") %:pragma GCC optimize("-fgcse-lm") %:pragma GCC optimize("-fipa-sra") %:pragma GCC optimize("-ftree-pre") %:pragma GCC optimize("-ftree-vrp") %:pragma GCC optimize("-fpeephole2") %:pragma GCC optimize("-ffast-math") %:pragma GCC optimize("-fsched-spec") %:pragma GCC optimize("unroll-loops") %:pragma GCC optimize("-falign-jumps") %:pragma GCC optimize("-falign-loops") %:pragma GCC optimize("-falign-labels") %:pragma GCC optimize("-fdevirtualize") %:pragma GCC optimize("-fcaller-saves") %:pragma GCC optimize("-fcrossjumping") %:pragma GCC optimize("-fthread-jumps") %:pragma GCC optimize("-funroll-loops") %:pragma GCC optimize("-fwhole-program") %:pragma GCC optimize("-freorder-blocks") %:pragma GCC optimize("-fschedule-insns") %:pragma GCC optimize("inline-functions") %:pragma GCC optimize("-ftree-tail-merge") %:pragma GCC optimize("-fschedule-insns2") %:pragma GCC optimize("-fstrict-aliasing") %:pragma GCC optimize("-fstrict-overflow") %:pragma GCC optimize("-falign-functions") %:pragma GCC optimize("-fcse-skip-blocks") %:pragma GCC optimize("-fcse-follow-jumps") %:pragma GCC optimize("-fsched-interblock") %:pragma GCC optimize("-fpartial-inlining") %:pragma GCC optimize("no-stack-protector") %:pragma GCC optimize("-freorder-functions") %:pragma GCC optimize("-findirect-inlining") %:pragma GCC optimize("-fhoist-adjacent-loads") %:pragma GCC optimize("-frerun-cse-after-loop") %:pragma GCC optimize("inline-small-functions") %:pragma GCC optimize("-finline-small-functions") %:pragma GCC optimize("-ftree-switch-conversion") %:pragma GCC optimize("-foptimize-sibling-calls") %:pragma GCC optimize("-fexpensive-optimizations") %:pragma GCC optimize("-funsafe-loop-optimizations") %:pragma GCC optimize("inline-functions-called-once") %:pragma GCC optimize("-fdelete-null-pointer-checks") #include<cstdio> #include<cmath> #include<algorithm> #define BPM 10007 #define N 4010 using namespace std; int n,m,k,frct,prit,fft[N],sum,m1; int pri[N],frc[N],ff[N][N],ys[10000001],f[N][N]; void dfs(int x,int zf,int ans)//容斥 {if(x>prit) {sum+=m1/ans*zf;return;}dfs(x+1,zf,ans);dfs(x+1,-zf,ans*pri[x]); } int main() {scanf("%d%d%d",&n,&m,&k);int sk=sqrt(k);for(int i=1;i<=sk;i++){if(k%i==0){frc[++frct]=i;if(k/i>sk) frc[++frct]=k/i;}}//求約數(shù)sort(frc+1,frc+1+frct);int tmp=k;for(int i=2;i<=sk;i++){if(tmp==1) break;if(tmp%i==0){pri[++prit]=i;while(tmp%i==0) tmp/=i;}}//求質(zhì)因子if(tmp!=1) pri[++prit]=tmp;sort(pri+1,pri+tmp+1);for(int i=1;i<=frct;i++){ys[frc[i]]=i;sum=0;m1=m/frc[i];dfs(1,1,1);f[1][i]=sum%BPM;}//計(jì)算f[1]for(int i=1;i<=frct;i++)for(int j=1;j<=i;j++)if(frc[i]%frc[j]==0)ff[i][++fft[i]]=j;//預(yù)處理關(guān)系for(int i=2;i<=n;i++)for(int j=1;j<=frct;j++){if(!fft[j]) continue;for(int k=1;k<=fft[j];k++)f[i][j]=(f[i][j]+f[i-1][ff[j][k]]*f[1][ys[frc[j]/frc[ff[j][k]]]])%BPM;//動(dòng)態(tài)轉(zhuǎn)移}printf("%d",f[n][frct]); }總結(jié)
以上是生活随笔為你收集整理的nssl1176-轨道【数论,Dp】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 大明湖畔夏雨荷什么梗 大明湖畔夏雨荷是什
- 下一篇: 张檬演过哪些电视剧 你看过几部