poj3421
题目链接:https://vjudge.net/problem/POJ-3421
这题一开始直接把约数全部枚举出来,然后用LIS的方法求,结果一直tle......明明900000的时候约数个数才100+,用LIS应该没问题,可能是数据组数很多?后来用质因数分解,复杂度确实降下来很多,因为主要的复杂度在分解质因数上,这几乎可以忽略不计。设n=p1^a1*p2^a2*...*pk^ak,则长度len=a1+...ak,考虑将k种len个素数排列,逐个乘得到链。如果两个排列不同,则链不同。(例如排列为2 2 5 5,链为2 4 20 100),那么方案数等价于求有重复元素的全排列,ans=(len)!/(a1!*a2!*...*ak!);
1 #include<cstdio> 2 #include<cstring> 3 #define ll long long 4 using namespace std; 5 const int maxn=1100000+10; 6 int p[maxn],pr[maxn],num[100]; 7 int n,i,j,k,len,ans,t,m,s; 8 ll tmp; 9 10 ll fac(int x){if (x==1) return 1;else return x*fac(x-1);} 11 12 int main(){ 13 t=0; 14 for (i=2;i<maxn;i++) 15 if (p[i]==0){ 16 pr[++t]=i; 17 for (j=i+i;j<maxn;j+=i) p[j]=1; 18 } 19 while (~scanf("%d",&n)){ 20 k=0; 21 memset(num,0,sizeof(num)); 22 for (i=1;i<=t;i++){ 23 if (n==1) break; 24 if (p[n]==0) { 25 k++;num[k]++;break; 26 } 27 if (n%pr[i]==0){ 28 k++; 29 while (n%pr[i]==0){ 30 n/=pr[i];num[k]++; 31 } 32 } 33 } 34 len=0;ans=1;tmp=1; 35 for (i=1;i<=k;i++) len+=num[i]; 36 for (i=1;i<=k;i++) tmp*=fac(num[i]); 37 ans=fac(len)/tmp; 38 printf("%d %d\n",len,ans); 39 } 40 return 0; 41 }
poj3292
题目链接:https://vjudge.net/problem/POJ-3292
用类似埃氏筛的方法求出1到1000001的所有H素数,再用f[i]表示前i个数中有多少半素H数判断一个数是不是半素H数一开始tle了,后来加了个判断条件就过了:注意半素的H数只有两个除了本身的H素因子(可重复)。所以验证一个数a是不是半素H数,只要找到一个是它的约数的H素数b,判断a/b是不是H素数即可,然后break
1 #include<iostream> 2 #include<cstring> 3 using namespace std; 4 const int maxn=1000+10; 5 int pr[maxn],p[maxn],f[maxn]; 6 int n,t,i,j,k,b; 7 8 int main(){ 9 memset(p,0,sizeof(p)); 10 t=0; 11 for (i=1;i<=4;i++) p[i]=1; 12 for (i=5;i<maxn;i++){ 13 if (i%4!=1) { 14 p[i]=1;continue; 15 } 16 if (p[i]==0){ 17 pr[++t]=i;k=5; 18 while (i*k<maxn){ 19 p[i*k]=1;k+=4; 20 } 21 } 22 } 23 memset(f,0,sizeof(f)); 24 for (i=1;i<maxn;i++){ 25 if (i%4!=1||(i%4==1&&p[i]==0)) { 26 f[i]=f[i-1];continue; 27 } 28 for (j=1;j<=t;j++) 29 if (i%pr[j]==0){ 30 k=i/pr[j]; 31 if (p[k]==0) f[i]=f[i-1]+1; else f[i]=f[i-1]; 32 break; 33 } 34 } 35 cin>>n; 36 while (n!=0){ 37 cout<<n<<' '<<f[n]<<endl;cin>>n; 38 } 39 return 0; 40 }
poj2689待写......