Math_4
大胖的超级数字
【问题描述】
大胖研究出了一种数字,名字叫做超级数。
这种数字有一个非常奇葩的属性,就跟大胖样的。
对于每一个超级数,其实都是对于给定的一个正整数
N
的阶乘的一种
现在大胖想知道,对应于某一个正整数
N
,到底有多少个超级数?
答案对
【输入】
输入文件名supernum.in。
一行两个正整数,分别为
N
,
【输出】
输出文件名supernum.out。
一个整数,代表对应于
N
和
【输入样例】
2 1
【输出样例】
1
【数据范围】
对于
对于
50%
的数据,保证有
n≤1000000
。
对于
100%
的数据,保证有
n≤1015
,
K>N/500
。
Solution
若
x
在
设
则
则 B 的每一位都有
所以我们只需要求出 ti 即可。
注意到,若 ti<k ,则 ⌊ti/k⌋+1=1 ,并不影响答案,而 k 超大,所以我们要筛的素数不多,
这样我们就可以求出
Bk
绝对能够整除
x
的
同理,可以求出
Bk+1
绝对能够整除
x
的
相减即可。
至于如何在 n! 中求出素数的指数,就不用我说了吧,度娘欢迎你。
Code
#include <iostream>
#include <cstdio>
#define LL long long
#define MAXN 500
#define MOD 1000000009
using namespace std;
LL n,k;
LL prime[MAXN+10];
bool no_prime[MAXN+10];
LL work(LL x,LL y){
LL ans=1;
for(LL i=1;prime[i]<=x;i++){
LL tmp=1,pre=x,cnt=0,t=0;
do{
tmp*=prime[i];
cnt++;
t+=(cnt-1)*(pre-x/tmp);
pre=x/tmp;
}while(tmp<=x);
if(t/y==0)break;
ans=(ans*(t/y+1)%MOD);
}
return ans;
}
int main(){
freopen("supernum.in","r",stdin);
freopen("supernum.out","w",stdout);
for(LL i=2;i<=MAXN;i++){
if(!no_prime[i])prime[++prime[0]]=i;
for(LL j=1;prime[j]*i<=MAXN;j++){
no_prime[prime[j]*i]=true;
if(i%prime[j]==0)break;
}
}
scanf("%lld%lld",&n,&k);
printf("%lld\n",((work(n,k)-work(n,k+1))%MOD+MOD)%MOD);
return 0;
}
大胖的神奇路径
【问题描述】
大胖最近在锻炼身体。(格式,格式,真的只是格式)
他家有一个无比巨大无比巨大的南北向跑道。
我们可以把这条跑道视作一个数轴,大胖家的位置在原点。
这天,大胖收到了大胖父母的指令,要求大胖今天要跑
N
次,每次
大胖最近虐现哥出的题目虐到无聊了,于是他决定,他要向南跑
X
次,而且每次大胖都希望自己不出现在自己家的北方。
他想知道,有多少种不同的方案满足自己的要求?答案对
【输入】
输入文件名为road.in。
输入可能包含若干组数据,每个数据占一行,包含两个整数,分别为N和X。
【输出】
输出文件名为road.out。
对应输入中每组数据,输出一行一个整数代表满足要求的不同方案数。
若不存在合法的要求,则输出
0
。
【输入样例】
1 1
【输出样例】
1
【数据范围】
对于
对于
50%
的数据,保证有
n≤103
。
对于
70%
的数据,保证有
n≤106
,而且数据只有一组。
对于
100%
的数据,保证有
n≤106
,
0≤X≤N
,数据组数不超过
1000
。
Solution
将向南走看作向右走,向北走看作像上走,就转化成了 网格 这道题。
Code
#include <iostream>
#include <cstdio>
#define LL long long
#define MAXN 1000000
#define MOD 1000000007
using namespace std;
LL power(LL x,LL y,LL p){
if(y==0)return 1;
if(y==1)return x%p;
LL tmp=power(x,y/2,p);
tmp=tmp*tmp%p;
if(y&1)tmp=tmp*(x%p)%p;
return tmp;
}
LL n,x;
LL jie[MAXN+10],ni[MAXN+10];
int main(){
freopen("road.in","r",stdin);
freopen("road.out","w",stdout);
jie[0]=ni[0]=1;
for(LL i=1;i<=MAXN;i++)jie[i]=jie[i-1]*i%MOD;
ni[MAXN]=power(jie[MAXN],MOD-2,MOD);
for(LL i=MAXN-1;i>=1;i--)ni[i]=ni[i+1]*(i+1)%MOD;
while(scanf("%lld%lld",&n,&x)!=EOF){
if(x<n-x){
printf("0\n");
continue;
}
printf("%lld\n",((jie[n]*ni[n-x]%MOD*ni[x]%MOD-jie[n]*ni[n-x-1]%MOD*ni[x+1]%MOD)%MOD+MOD)%MOD);
}
return 0;
}
大胖的中国象棋
【问题描述】
大胖最近在玩中国象棋。
他非常喜欢“車”这个棋子,因为读音和猪肉很像。
而且車能上能下,能左能右,是外出旅行,杀人放火之必需必备必不可少之良器。
现在有一个
N×N
的棋盘,大胖有
N
个車,这些車从
请输出方案数对一个数
M
的模值。
【输入】
输入文件名为chess.in
输入仅一行,包括两个正整数
【输出】
输出文件名为chess.out
输出仅一行,表示方案数对
【输入样例】
2 1000
【输出样例】
1
【数据范围】
对于
50%
的数据,保证有
n≤106
。
对于
100%
的数据,保证有
n≤1017
,
m<=106
。
Solution
考虑每一个車,设它的坐标为
(x,y)
。
则
1 ~ n
的所有的车的
x
坐标为
所以上错排公式,
同理,
y
坐标也是如此。
所以
打表发现,答案每 m <script type="math/tex" id="MathJax-Element-1047">m</script> 一循环。
Code
#include <iostream>
#include <cstdio>
#define LL long long
using namespace std;
LL n,m;
LL s[1000010];
int main(){
freopen("chess.in","r",stdin);
freopen("chess.out","w",stdout);
scanf("%lld%lld",&n,&m);
s[1]=0;s[2]=1;
n=(n-1)%m+1;
for(LL i=3;i<=n;i++)
s[i]=((i-1)%m)*((s[i-1]+s[i-2])%m)%m;
printf("%lld\n",s[n]*s[n]%m);
return 0;
}