题目描述
数学的王国里,有一些约数国王……约数国王的定义是这样的:一个大于1的整数n,如果它约数的个数比1~n-1的每个整数的约数的个数都要多,那么我们就称它为约数国王。聪明的(______)在奥数书上认识了它们,于是产生了一个问题:他想知道L到R之间一共有多少个约数国王?它们分别又是谁?
输入
输入文件只有一行,包含一个l,一个r,表示小明想知道的范围。
输出
只有一行,第一个数h,表示l~r内一共有多少个约数国王,接下来h个从小到大的数(为了防止国王们打架,你需要按顺序输出。),表示约数国王分别是谁。
样例输入
1 100
样例输出
8 2 4 6 12 24 36 48 60
数据范围限制
对于30%的数据,1<=l<=r<=200000。
对于50%的数据,1<=l<=r<=500000。
对于70%的数据,保证最大的约数国王的约数的个数不大于1000。
对于100%的数据,1<=l<=r, 并且保证l,r在64位整型以内,最大的约数国王的约数的个数不大于200000。
首先很肯定的 是暴力:
#include
using namespace std;
int biao[10][10] = {{0,0},{0,1},{0,2,4,8,6},{0,3,9,7,1},{0,4,6},{5,5},{6,6},{0,7,9,3,1},{0,8,4,2,6},{0,9,1}};
//手动打表模拟各位次方
int len[10] = {1,1,4,4,2,1,1,4,4,2};
int t,ans,n,a,b;
int main()
{
//freopen("superpow.in","r",stdin);
//freopen("superpow.out","w",stdout);
scanf("%d",&t);
while (t--)
{
ans = 1;
scanf("%d",&n);
for (int i = 1;i <= n;i++)
{
scanf("%d%d",&a,&b);
int x = a;
while (--b)
{
if (x == len[a]) x = biao[a][x];
else x = biao[a][x % len[a]];
}
ans *= x;
ans %= 10;
}
printf("%d\n",ans);
}
return 0;
}
首先我们可以知道任意一个整数都可以理解为多个素数的乘积(咀嚼一下)
辣么,我们可以得到如下公式
x = A 1 P 1 ∗ A 2 P 2 ∗ A 3 P 3 ∗ … … A k P k x = A_1 ^ {P_1} * A_2^ {P_2} *A_3^ {P_3} * ……A_k^ {P_k} x=A1P1∗A2P2∗A3P3∗……AkPk
也就是说我们只要求这个,就是 x x x的约数个数:(全排列问题嘛, p [ i ] p[i] p[i]种情况还有 k k k它本身)
∏ k i = 1 ( P i + 1 ) \prod \frac{k}{i=1} (P_i + 1) ∏i=1k(Pi+1)
然后显而易见,我们就能看出 一个很简单的式子
F [ i ] = m i n ( f [ k ] [ i ] ∣ 0 < k ≤ ∞ ) F[i] = min(f[k][i] | 0 < k \leq \infty) F[i]=min(f[k][i]∣0<k≤∞)
申明一个F[ ]数组,这个数组用于储存 i i i个质因子的数中最小是谁,然后我们可知这样的数组是一定存在且可被求出的。
此时提到了一个 f f f数组,又是用来干嘛呢?
其实这个数组是用来储存选择了 k k k个前质因数(如果不是前几个不一定最大,有想法可以自己证明),有i个约数的数的
巴拉拉魔法能量,敲黑板
f [ k + 1 ] [ i + 1 ] = m i n ( f [ k ] [ i ] ∗ p r i m e [ k + 1 ] j ∣ 0 < j ≤ ∞ ) f[k + 1][i + 1] = min(f[k][i] * prime[k + 1] ^j|0 < j \leq \infty) f[k+1][i+1]=min(f[k][i]∗prime[k+1]j∣0<j≤∞)
此处的 p r i m e [ i ] prime[i] prime[i]是第i个素数(抱歉,要自己打,想用现成的函数门都没得)——筛吧筛吧我的骄傲放纵
int isPrime(int n)//julao倾情贡献尊享暴力筛代码
{
float n_sqrt;
if(n <= 3) return 1;
if(n%6!=1 && n%6!=5) return 0;//julao菠萝蜜之优化
n_sqrt=floor(sqrt((float)n));
for(int i=5;i<=n_sqrt;i+=6) if(n%(i)==0 || n%(i+2)==0) return 0;
return 1;
}
有了蜜汁筛的强力加持,我们的程序便呼之欲出了——