Codeforces Round #304 (Div. 2) D. Soldier and Number Game
思路
对于某一个数,要想玩最多回合,就每次取其一个质因数,直到取完,因此答案就是质因数的个数。由此可知,对于,答案就是所有数字质因数个数的总和。因此只要提前维护出质因数个数的前缀和就可以轻松算出答案。
怎么求质因数的个数呢?对于一个合数,假设有一个比它更小的合数以及一个质数,使得,那么就可以用和的质因数个数相加得到的质因数个数。这个过程和欧拉筛的过程是一致的,因此可以在筛的过程中计算出当前被筛掉的合数的质因数个数。
代码
#include<bits/stdc++.h>
#define rep(i,st,ed) for(int i=st;i<=ed;++i)
#define bl(u,i) for(int i=head[u];i;i=e[i].nxt)
#define LLM LONG_LONG_MAX
#define LLm LONG_LONG_MIN
#define pii pair<ll,ll>
typedef long long ll;
typedef double db;
using namespace std;
const ll INF=0x3f3f3f3f;
void read() {}
void say() {}
void say_() {}
template <typename T, typename... T2>
inline void read(T &_, T2 &... oth)
{
int __=0;
_=0;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
__=1;
ch=getchar();
}
while(isdigit(ch))
{
_=_*10+ch-48;
ch=getchar();
}
_=__?-_:_;
read(oth...);
}
template <typename T>
void Out(T _)
{
if(_<0)
{
putchar('-');
_=-_;
}
if(_>=10)
Out(_/10);
putchar(_%10+'0');
}
template <typename T, typename... T2>
inline void say(T _, T2... oth)
{
Out(_);
putchar('\n');
say(oth...);
}
template <typename T, typename... T2>
inline void say_(T _, T2... oth)
{
Out(_);
putchar(' ');
say_(oth...);
}
/*#################################*/
const ll N=5E6+10;
ll n,l,r;
ll f[N],sum[N],vis[N];
vector<ll> pri;
void sieve()
{
rep(i,2,5E6)
{
if(!vis[i])
{
pri.emplace_back(i);
f[i]=1;
}
for(auto k:pri)
{
if(i*k>5e6)
break;
vis[i*k]=1;
f[i*k]=f[i]+f[k];
if(i%k==0)
break;
}
}
}
int main()
{
sieve();
rep(i,2,5e6)
sum[i]=sum[i-1]+f[i];
read(n);
while(n--)
{
read(r,l);
say(sum[r]-sum[l]);
}
}
2021年“图森未来杯”全国程序设计邀请赛 D题
思路
对原式变形得到,因此转化成了判断阶乘是否能够整除的问题。设关于质数的函数,使得。当且仅当对于任意质数,都有时,。
给定,如何求呢?因为是质数,因此只有的倍数才会对产生贡献。每个的倍数会产生的贡献,每个的倍数会产生的贡献,但由于的倍数与的倍数重合,因此的倍数只会额外产生的贡献,以此类推(具体可参考《具体数学》第四章)。而在内的倍数共有个,因此。
代码
#include<bits/stdc++.h>
#define rep(i,st,ed) for(int i=st;i<=ed;++i)
#define bl(u,i) for(int i=head[u];i;i=e[i].nxt)
#define LLM LONG_LONG_MAX
#define LLm LONG_LONG_MIN
#define pii pair<ll,ll>
typedef long long ll;
typedef double db;
using namespace std;
const ll INF=0x3f3f3f3f;
void read() {}
void say() {}
void say_() {}
template <typename T, typename... T2>
inline void read(T &_, T2 &... oth)
{
int __=0;
_=0;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
__=1;
ch=getchar();
}
while(isdigit(ch))
{
_=_*10+ch-48;
ch=getchar();
}
_=__?-_:_;
read(oth...);
}
template <typename T>
void Out(T _)
{
if(_<0)
{
putchar('-');
_=-_;
}
if(_>=10)
Out(_/10);
putchar(_%10+'0');
}
template <typename T, typename... T2>
inline void say(T _, T2... oth)
{
Out(_);
putchar('\n');
say(oth...);
}
template <typename T, typename... T2>
inline void say_(T _, T2... oth)
{
Out(_);
putchar(' ');
say_(oth...);
}
/*#################################*/
const ll N=1E7+10;
ll a,b,c,d;
ll vis[N];
vector<ll> pri;
void sieve()
{
rep(i,2,1e7)
{
if(!vis[i])
{
pri.emplace_back(i);
vis[i]=1;
}
for(auto k:pri)
{
if(i*k>1e7)
break;
vis[i*k]=1;
if(i%k==0)
break;
}
}
}
ll fp(ll x,ll p)
{
return x==0?0:fp(x/p,p)+x/p;
}
void solve()
{
read(a,b,c,d);
for(auto k:pri)
{
ll bc=fp(b,k)+fp(c-1,k),ad=fp(a-1,k)+fp(d,k);
if(bc>ad)
{
puts("NO");
return;
}
}
puts("YES");
}
int main()
{
sieve();
int _;
cin>>_;
while(_--)
{
solve();
}
}