数论+打表
A的所有因子和位B,B的所有的因子和为A,则称{A,B}是一对ooxx number
输入数字n,求出[1,n]里面有多少对ooxx number,其中(A,B),(B,A)这样算作一对
n最大为5百万(50000000)
hits 220= (1+2+4+71+142) <--- 284, 284= (1+2+4+5+10+11+20+22+44+55+110) <--- 220。 220 and 280 is a pair of ooxx numbers
sample input
300
1300
sample output
1
2
定义sum[i]=i的因子和,用筛法来构建i
枚举因子i,那么2i,3i,4i…………都包含i这个因子,i都是它们因子和的一部分,所以要 sum[2i] += i; sum[3i] += i; sum[4i] += i;
用筛法能求出所有的sum[i],不过还没完,它们都缺了1,不过可以等下加进去即可
然后就是看看所有的sum[i],
m = sum[i] + 1 , 且 i = sum[m] + 1 ;
那么(m,i)就是一对ooxxnumber,这这个判断只需要扫一遍sum数组即可
以上过程可以记录下所有的对,用时大概是2s多,会发现这些对其实不多,直接输出到文件中,然后打表即可
在每个case中输入n后,扫描对,找到合适的对就计数
打表程序
#include <cstdio> #include <cstring> const int N = 5000000 ; int sum[N+10]; void init() { memset(sum,0,sizeof(sum)); int m = N/2; for(int i=2; i<=m; i++) for(int j=i+i; j<=N; j+=i) sum[j] += i; for(int i=2; i<=N; i++) { int mm= sum[i]+1; if(mm <= N && mm>i && sum[mm]+1 == i ) printf("%d,%d,",i,mm); } } int main() { freopen("list.txt","w",stdout); init(); return 0; }
最后的程序
#include <cstdio> #include <cstring> int sum[10000][2]={220,284,1184,1210, 2620,2924,5020,5564, 6232,6368,10744,10856, 12285,14595,17296,18416, 63020,76084,66928,66992, 67095,71145,69615,87633, 79750,88730,100485,124155, 122265,139815,122368,123152, 141664,153176,142310,168730, 171856,176336,176272,180848, 185368,203432,196724,202444, 280540,365084,308620,389924, 319550,430402,356408,399592, 437456,455344,469028,486178, 503056,514736,522405,525915, 600392,669688,609928,686072, 624184,691256,635624,712216, 643336,652664,667964,783556, 726104,796696,802725,863835, 879712,901424,898216,980984, 947835,1125765,998104,1043096, 1077890,1099390,1154450,1189150, 1156870,1292570,1175265,1438983, 1185376,1286744,1280565,1340235, 1328470,1483850,1358595,1486845, 1392368,1464592,1466150,1747930, 1468324,1749212,1511930,1598470, 1669910,2062570,1798875,1870245, 2082464,2090656,2236570,2429030, 2652728,2941672,2723792,2874064, 2728726,3077354,2739704,2928136, 2802416,2947216,2803580,3716164, 3276856,3721544,3606850,3892670, 3786904,4300136,3805264,4006736, 4238984,4314616,4246130,4488910, 4259750,4445050 }; int main() { int n; while(scanf("%d",&n)!=EOF) { int res = 0; for(int i=0; sum[i][0]!=0 && sum[i][0] < n; i++) { if(sum[i][0] <= n && sum[i][1] <= n) res ++; } printf("%d\n",res); } return 0; }