A. Bi-shoe and Phi-shoe: 给出一个数列a,对于其中的每个元素,求出欧拉函数值不小于此元素的最小数。
题解:由欧拉函数的定义可以得到,对于一个数字x,欧拉函数值不小于x的最小数是不小于x的最小素数。因此先打出素数表,再二分地对于每一个元素找出不小于它的最小素数即可。
#include
#define maxn 10050
#define maxm 2000050
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
typedef long long ll;
int t,n,a,p,kase=0;
int pri[maxm];
bool flag[maxm];
void init(int x)
{
for(int i=0;i<=x;i++)flag[i]=1;
flag[0]=flag[1]=0;
p=0;
for(int i=2;i<=x;i++)
{
if(flag[i])
{
pri[p++]=i;
for(int j=i*2;j<=x;j+=i)
flag[j]=0;
}
}
}
int main()
{
scanf("%d",&t);
init(2e6);
while(t--)
{
scanf("%d",&n);
ll ans=0;
for(int i=0;i
C. Aladdin and the Flying Carpet: 给定两个数a和b,求b到sqrt(a)中有多少个数是a的因数。
题解:有这样一个定理:如果一个数x的唯一分解式为(p1^e1)*(p2^e2)*……*(pn^en),那么x的因数数目就是(1+e1)*(1+e2)*……*(1+en)。显然1-sqrt(x)内的因数数目就是总的因数数目除以2。然后枚举1-b减去这个区间内的因子即可。
#include
#define maxn 1000050
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
typedef long long ll;
int t,num=0,p,kase=0;
ll a,b;
int pri[maxn];
bool flag[maxn];
void init(int x)
{
for(int i=0;i<=x;i++)flag[i]=1;
flag[0]=flag[1]=0;
for(int i=2;i<=sqrt(x);i++)
{
if(flag[i])
{
for(int j=i*i;j<=x;j+=i)
flag[j]=0;
}
}
for(int i=2;i<=x;i++)
{
if(flag[i])
pri[num++]=i;
}
}
ll coun(ll x)
{
ll cnt=x;
ll cur=0,ans=1;
int i=0;
if(x==0)return 0;
while(i1)ans*=2;
return ans;
}
int main()
{
scanf("%d",&t);
init(1000000);
while(t--)
{
scanf("%lld%lld",&a,&b);
ll ans;
if(b>=sqrt(1.0*a))ans=0;
else
{
ans=coun(a)/2;
for(ll i=1;i
D. Sigma Function: 定义一个函数如下图,给定n,问1-n中有多少个数的函数值为偶数。
题解:只要某一项为偶数,整个函数值就为偶数。所以可以先讨论奇数的情况。每一项可以表示为1+pi+p2^2+……+pi^ei,只有pi与ei同时为奇数时,这项的结果才会为偶数。也就是说对于唯一分解式中的pi^ei,有pi为偶或者pi奇ei偶的情况。
pi偶ei偶与pi奇ei偶的情况中,既然指数都为偶数,那么这就一定是完全平方数。而pi偶ei奇的情况中,一个数的偶素因子只可能为2,也就是说是2的奇数次方。提出一个2来,就可以看出这个数显然是某个完全平方数的2倍。
也就是说一个数如果不是完全平方数或者完全平方数的两倍,它的函数值就为偶数。
因此答案为n-sqrt(n)-sqrt(n/2)。
E. Leading and Tailing: 给定两个数n和k,求n^k的前3位和后3位数。
题解:后3位只要在快速幂中对1000取模即可。前三位:
F. Goldbach's Conjecture: 给定一个数n,问存在多少对素数(a,b)满足a+b=n。
题解:打出素数表来,枚举小于等于n/2的每个素数,看n和它之差是不是素数即可。
G. Harmonic Number(II): 给定n,求n/i(i from 1 to n)之和。
题解:先直接处理出1-sqrt(n)的值,对于后面的值可以利用它们求出,例如值为1的有(n/1-n/2)项,值为2的有(n/2-n/3)项,直至n/i等于n/i+1。这之中n/sqrt(n)被计算了两次,需要减去。
#include
#define maxn 10000050
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
typedef long long ll;
const ll mod = 1000;
int t,n,kase=0;
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
ll ans=0;
for(ll i=1;i*i<=n;i++)
{
ans+=(n/i)*(i-n/(n/i+1));
if(n/i!=i)
ans+=i*(n/i-n/(i+1));
}
printf("Case %d: %lld\n",++kase,ans);
}
return 0;
}
H. Pairs Forming LCM: 给定正整数n,求有多少对(i,j)满足lcm(i,j)=n。
题解:对于正整数a和b,lcm(a,b)是a,b的所有素因子在其唯一分解式中较高次幂的乘积。先将n分解,对于每一项pi^ei,有两种情况:
若pi在a中的指数等于ei,那么其在b中的指数可以取0-ei,有(ei+1)种情况。若不等于ei,那么在b中的指数必为ei,a中指数可以取ei种情况。那么对于n的每个素因子都有2*ei+1种情况,将其全部相乘得到ans。考虑a和b的大小关系,除了a,b都为n的情况,都出现了两次,因此最终答案就是ans/2+1。
I. Harmonic Number: 给定n,求调和级数的前n项。
题解:这个似乎和数论没什么关系啊……?采用了分段打表的思想,每100项的结果存起来,每次只需枚举不足整百的部分即可。
#include
#define maxn 1000050
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
typedef long long ll;
const ll mod = 1000;
int t,n,kase=0;
double ans[maxn];
void init()
{
double tmp=0;
for(int i=1;i<=100000000;i++)
{
tmp+=(1.0/i);
if(i%100==0)
ans[i/100]=tmp;
}
}
int main()
{
scanf("%d",&t);
init();
while(t--)
{
scanf("%d",&n);
double tmp=ans[n/100];
for(int i=n/100*100+1;i<=n;i++)
tmp+=(1.0/i);
printf("Case %d: %.10lf\n",++kase,tmp);
}
return 0;
}
J. Mysterious Bacteria: 给定整数x,寻找一个尽可能小的数使得x为这个数的幂,求这个幂指数。
题解:将x唯一分解,则ans=gcd(e1,e2,……,ek)。有一个坑点是x可能为负,此时结果的幂指数不能为偶数。
#include
#define maxn 10000050
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
typedef long long ll;
const ll mod = 1000;
int t,num=0,kase=0;
ll n;
int pri[maxn/10];
bool flag[maxn];
void init()
{
memset(flag,0,sizeof(flag));
flag[0]=flag[1]=1;
for(int i=2;i<=sqrt(10000000);i++)
{
if(!flag[i])
{
for(int j=i*i;j<=10000000;j+=i)
flag[j]=1;
}
}
for(int i=2;i<=10000000;i++)
{
if(!flag[i])
pri[num++]=i;
}
}
int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
int cal(ll x)
{
int cur,ans=0;
ll tmp=x;
for(int i=0;i1)ans=gcd(ans,1);
return ans;
}
int main()
{
scanf("%d",&t);
init();
while(t--)
{
scanf("%lld",&n);
bool vis=0;
if(n<0)
{
n=(-n);
vis=1;
}
int ans=cal(n);
if(vis&&ans%2==0)
while(ans%2==0)ans/=2;
printf("Case %d: %d\n",++kase,ans);
}
return 0;
}
K. Large Division: 200位大数对int取模
题解:同余定理,按位取模即可。
L. Fantasy of a Summation: 给出一个长度为n的数列,选k个可重复的数字有n^k种方法,求所有方案选出的元素之和。
题解:进行了n^k次加法,每个数被选中的概率都是k/n,因此答案为sum*k*n^(k-1)。
M. Help Hanzo: 问a-b中有多少个素数。b-a<=1e5。
题解:区间素数筛法模板。
#include
#define maxn 100050
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
typedef long long ll;
int t,cont,kase=0;
ll m,n,z,p[maxn];
bool flag[maxn],f[maxn];
void getPrime()
{
z=0;
memset(flag,true,sizeof(flag));
for (int i=2;i<=100000;i++)
{
if (flag[i])
{
p[z++]=i;
for (int j=i*i;j<=100000;j+=i)
flag[j]=0;
}
}
}
int main()
{
ll sz,k;
getPrime();
scanf("%d",&t);
while(t--)
{
scanf("%lld%lld",&m,&n);
cont=0;
if(n<70000)
{
for(ll i=m;i<=n;i++)
if(flag[i] && i!=1)cont++;
}
else
{
if(m<=2) m=2;
sz=n-m;
for(ll i=0;i<=sz;i++)
f[i]=true;
for(i=0;i
N. Trailing Zeros(III): 给出一个数n,问是否存在x使得x的阶乘末尾恰好有n个0。若存在求出最小的x。
题解:一个数中含有多少个5,阶乘的末尾就会含有多少个0。用二分的方法找出这个最小的点。
#include
#define maxn 100050
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
typedef long long ll;
int t,n,kase=0;
int getnum(int x)
{
int ans=0;
while(x)
{
ans+=(x/5);
x/=5;
}
return ans;
}
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
int l=1,r=1000000000,ans;
while(l<=r)
{
int mid=(l+r)/2;
if(getnum(mid)>=n)
{
ans=mid;
r=mid-1;
}
else l=mid+1;
}
printf("Case %d: ",++kase);
if(getnum(ans)==n)printf("%d\n",ans);
else printf("impossible\n");
}
return 0;
}
O. GCD-Extreme(II): 给定n,求每一对小于n的(i,j)的gcd之和。
题解:用b[n]表示1-n-1与n的gcd之和,即sum[n]=sum[n-1]+b[n]。
用a[i]表示gcd(n,x)=i的x的个数,显然b[n]=Sum(i*a[i])。所以只需求a[i]:gcd(n,x)=i,即gcd(n/i,x/i)=1。
因此只需要求出phi[i],即可知道与n/i互质的数目,这样就可以求解了。
#include
#define maxn 4000050
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
typedef long long ll;
int n,phi[maxn];
ll f[maxn],sum[maxn];
void init()
{
memset(phi,0,sizeof(phi));
phi[1]=1;
for(int i=2;i
R. 青蛙的约会:有两只青蛙分别在长度为l的环的a,b位置,以x,y速度同向跳跃,问多长时间后可以相遇。
S. C Looooops: 对于循环for(int i=a,i!=b;i+=c),在模2^k下需要运行多少次才会跳出循环。
题解:如下图,解方程即可。
V. Maxmium GCD: 给出一个数列,求两两组合gcd的最大值。
题解:直接暴力就行,但是要注意读入的方法,可以用字符串读入。
W. Prime Time: 定义f(x)=x*x+x+41,求a-b的函数值中素数的比例。
题解:1e4的数据,预处理一下函数值的素性,然后对于每次查询维护前缀和即可。
Y. Super Powers: 输出1-2^64-1中同时是两个或两个以上数的幂的数。
题解:要想进行拆分,幂指数必须是合数。也就是幂指数只会是4-64中的合数。然后枚举底数进行判断,底数大约在1e5之内。为节省时间当幂达到2^64时就跳出循环,对于底数i最大的幂指数就是ceil(64/lgi*lg2)-1。由于存在略大于2^64的情况,此题需要使用unsigned long long。
#include
#define maxn 105
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
typedef unsigned long long ull;
mapm;
map::iterator it;
bool flag[maxn];
int p[maxn],num=0;
void init()
{
memset(flag,0,sizeof(flag));
for(int i=2;i<=100;i++)
{
if(!flag[i])
{
for(int j=i*2;j<=100;j+=i)
flag[j]=1;
}
}
for(int i=4;i<=100;i++)
{
if(flag[i])
p[num++]=i;
}
}
ull mi(ull a,int x)
{
if(x==0)return 1;
ull tmp=mi(a,x/2);
ull ans=tmp*tmp;
if(x%2==1)
ans*=a;
return ans;
}
int main()
{
init();
m[1]=INF;
for(int i=2;i<(1<<16);i++)
{
double t=ceil(64.0/log(i)*log(2))-1;
for(int j=0;p[j]<=t&&jfirst <