poj3421&poj3292&poj2689 基础数论

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 }
poj3421

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 }
poj3292

poj2689待写......

猜你喜欢

转载自www.cnblogs.com/edmunds/p/12748416.html