您的位置:首页 > 其它

Codeforces Round #304 (Div. 2)-D. Soldier and Number Game,素因子打表!

2016-06-07 13:12 357 查看
D. Soldier and Number Game

time limit per test
3 seconds

memory limit per test
256 megabytes

input
standard input

output
standard output

-> Link <-

   题目链接呈上;

  题意:两个人玩游戏,其中一个人选一个数n给另外一个人,然后每轮选一个数x使得n能被x整除,然后用n/=x;注意x>1;问要使得另一个人得分最高,最高多少;即最多能够玩几轮n变成了1,为了使游戏更加有趣,给出两个数a,b;n=a!/b!;其中数据范围是500,0000;

  思路:我们观察样例,第一组n=3!/1!=6,然后6可以选2或3进行整除,得到的还是2或3,因为这个时候变成了素数再选只能选本身才能整除;所以只有2轮;再看第二组,n=6!/3!=120;所以n=120/2=60/2=30/2=15/3=5/5=1;总共5轮,我们的目的是什么?要使得n尽量多整除几轮,所以每次都选一个最小的素因子来整除,这样所得的分才最高;那么选最小的素因子怎么选呢?我们观察到:6=2*3,120=2*2*2*3*5;明白了吧,这个n的拆分的素因子个数就是最多能整除的轮数,那么我们就是要求出n的素因子个数了,题目数据比较大,直接求得用到高精度,我们来看n是怎么得来的呢?n=a!/b!,题目已表明b<=a,所以n=(b+1)*(b+2)*(b+3)*...*a;,我们只需求出从b+1到a中的素因子个数就是答案了,基于数据太大,所以我们要打表求出
1 - 5000000中每个数的素因子数;

  然而比赛的时候想到了一种方法,却疏漏了一点致使成功离我们远去;我们观察到4=2*2,有2个,而8=2*2*2,有三个;再看6=2*3,有2个,12=6*2,有2+1个,所以当时想的方法就是用各个因子的素因子数来累加,来看这种思路代码:

const int N=5000000+10;
int a
;
int main()
{
memset(a,0,sizeof(a));
for(int i=2; i<=N; i++)
if(!a[i])//就是没考虑到这里,所以以为会超时直接不敢写了...............
{
for(int j=i;j<=N;j+=i)
a[j]=a[j/i]+1;
}
for(int i=2;i<=N;i++)//这里要注意累加,因为查询次数比较多,每次都用循环累加也是会超时的;
a[i]+=a[i-1];
int t,n,m;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
printf("%d\n",a
-a[m]);
}
return 0;
}


 再来看另一种思路打表代码:

const int N=5000000+10;
int a
;
int main()
{
memset(a,0,sizeof(a));
for(int i=2; i<=N; i++)//这居然也不超时..古凯队长也是叼;;
if(!a[i])
{
long long temp;
for(temp=i;temp<=N;temp*=i)
for(long long j=temp;j<=N;j+=temp)
a[j]++;//这种更好理解一点,直接加上去;
}
for(int i=2;i<=N;i++)
a[i]+=a[i-1];
int t,n,m;
scanf("%d",&t);
while(t--)
{
//        scanf("%d",&n);
//        printf("%d\n",a
);
scanf("%d%d",&n,&m);//其实当n==m时n==1,直接输出0,特判一下省时间;;
printf("%d\n",a
-a[m]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: