题意:定义K-维数M:如果M的因数个数为K,则M为K-维数。题目的要求是求第N个K-维数。N<10000,Kmax<=100,Kmax是K的最大质因数。如果K是一个kk-维数,则kk<=3。
分析: 如果M = x1^p1 * x2^p2 * ... * xn^pn (x1,x2...xn均为质数),则 K = (p1+1)*(p2+1)*...*(pn+1). 这道题重要的条件是:如果K是一个kk-维数,则kk<=3。根据这个条件可以确定K的范围。kk的取值只有三种1,2,3。如果kk=1,则K=1;如果kk=2,K=p(p为质数);如果kk=3,K=p^2(p为质数)。 分情况讨论,如果K = 1,则原数M只可能为1,因为只有1的因数个数为1。如果K = p(p为质数),则原数M = x^(p-1)(x也为质数),找到第n个数只需遍历一下质数表就可以了。如果K=p^2(p为质数),则原数M = x1^(p-1)*x2^(p-1) = (x1*x2)^(p-1) (x1,x2均为质数且不等),或者 M = x1^(K-1) (x1为质数)。这种情况下找到第n个K-维数就比较复杂了,首先要找到前10000个两个不等质数之积,在对质数表和两个质数积表进行扫描,找到第n个值。 这道题需要注定的还有最后的结果肯定是一个超出64位的整数,需要使用高精度进行幂的运算。
code:
1#include<iostream> 2#include<cmath> 3using namespace std; 4 5const int maxn=500000; 6const int mod=100000000; 7 8int prime[maxn]; 9int flag[maxn]; 10int px[10006]; 11int n,K,mark; 12 13struct bign 14{ 15 __int64 val[1000]; 16 int len; 17 bign(){memset(val,0,sizeof(val));len=1;} 18}; 19bign a,b,c,d,dd,e; 20 21int get_pri() 22{ 23 int i,j,k; 24 k=0; 25 memset(flag,0,sizeof(flag)); 26 flag[0]=flag[1]=1; 27 for(i=2;i<maxn;i++) 28 { 29 if(!flag[i])prime[k++]=i; 30 for(j=0;j<k&&prime[j]*i<maxn;j++) 31 { 32 flag[prime[j]*i]=1; 33 if(i%prime[j]==0)break; 34 } 35 } 36 return k; 37} 38 39void Init(bign &cc,int t) 40{ 41 int j=0; 42 43 while(t) 44 { 45 cc.val[j++]=t%mod; 46 t/=mod; 47 } 48 cc.len=j; 49 return ; 50} 51 52void multify(bign &aa,bign &bb) 53{ 54 int i,j; 55 memset(dd.val,0,sizeof(dd.val)); 56 dd.len =1; 57 for(i=0;i<aa.len;i++) 58 for(j=0;j<bb.len;j++) 59 { 60 dd.val[i+j]+=aa.val[i]*bb.val[j]; 61 dd.val[i+j+1]+=dd.val[i+j]/mod; 62 dd.val[i+j]%=mod; 63 } 64 65 dd.len=aa.len+bb.len; 66 if(dd.val[dd.len-1]==0)dd.len--; 67 aa=dd; 68 return ; 69} 70 71void power(bign &temp,bign &x,int y) 72{ 73 temp.len=1; 74 temp.val[0]=1; 75 while(y) 76 { 77 if(y&1)multify(temp,x); 78 multify(x,x); 79 y>>=1; 80 } 81 return ; 82} 83 84void cal_xx() 85{ 86 int i,j,k=0,t; 87 for(i=4;i<=100000;i++) 88 { 89 t=i; 90 for(j=0;prime[j]*prime[j]<t;j++) 91 { 92 if(t%prime[j])continue; 93 t=t/prime[j]; 94 if(!flag[t]) 95 px[k++]=i; 96 else break; 97 if(k==10000)break; 98 } 99 if(k==10000)break; 100 } 101} 102 103int cmp(bign &x,bign &y) 104{ 105 if(x.len>y.len)return 1; 106 if(x.len<y.len)return -1; 107 int i; 108 for(i=x.len-1;i>=0;i--) 109 { 110 if(x.val[i]>y.val[i]) 111 return 1; 112 if(x.val[i]<y.val[i]) 113 return -1; 114 } 115 return 0; 116} 117 118void solve( bign &t) 119{ 120 int i=0,j=0,k; 121 int f1=0,f2=0; 122 123 for(k=0;k<n;k++) 124 { 125 if(!f1) 126 { 127 Init(a,px[i]); 128// power(a,d,mark-1); 129 } 130 if(!f2) 131 { 132 Init(d,prime[j]); 133 power(b,d,mark+1); 134 } 135 if(cmp(a,b)==1) 136 { 137 if(k==n-1)e=b; 138 139 f1=1;f2=0; j++; 140 } 141 else 142 { 143 if(k==n-1)e=a; 144 145 f1=0;f2=1;i++; 146 } 147 } 148 power(t,e,mark-1); 149} 150 151void output(bign &x) 152{ 153 int i=x.len; 154// printf(" %d\n",i); 155 printf("%d",x.val[--i]); 156 while(i) 157 { 158 printf("%08d",x.val[--i]); 159 } 160 printf("\n"); 161} 162 163int main() 164{ 165 get_pri(); 166 cal_xx(); 167 while(EOF!=scanf("%d%d",&n,&K)) 168 { 169 if(K==1){printf("1\n");continue;} 170 171 mark=0; 172 173 if(flag[K]){mark=(int)sqrt(K*1.0);} 174 175 if(!mark) 176 { 177 Init(d,prime[n-1]); 178 power(c,d,K-1); 179 output(c); 180 } 181 else 182 { 183 solve(c); 184 output(c); 185 } 186 } 187 return 0; 188} 189
|
|
| 日 | 一 | 二 | 三 | 四 | 五 | 六 |
---|
27 | 28 | 29 | 30 | 31 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|
公告
常用链接
留言簿
随笔分类
随笔档案
文章分类
文章档案
搜索
最新评论
阅读排行榜
评论排行榜
|
|