Math_3
INDEX1
【问题描述】
INDEX 是谁?兄弟,这个问题你如果不知道我就只能怀疑你是从火星来的了。
但是,如果你真的不知道他是谁,那么,你可能和他拥有同一个故乡。
其实当年 INDEX 在火星上有
N
个基友和
基友和妹子排成一队,使得他能够站在最前面,领着他的基友后宫团游街(囧) 。
但是,他的妹子们的嫉妒心是很强的,如果两个妹子站在一起,肯定会为 INDEX 吵得
不可开交。
同时,INDEX 也是有老婆的人,他身后,也就是队伍的第一个人必须是他的基友后宫团的团长——他老婆(也就是说,
M
个妹子中有一个是他的老婆,为了使题目容易理解, 也就是第一个人已经确定是
而且, 他希望由一个基友来殿后。
现在 INDEX 想知道,他能够排成多少种不同的队伍,使得这个队伍满足他的要求?
【输入】
输入文件名为 Indexone.in。
输入一行包含两个整数
N
和
【输出】
输出文件名为 Indexone.out。
输出一行, 表示合法的队伍总数对
1000000007
的模值, 如果不存在何方方案则输出
0
。
【输入样例】
1 1
【输出样例】
1
【数据范围】
对于
对于另外
30%
的数据,保证有
1≤M≤10
。
对于
100%
的数据,保证有
1≤N,M≤1000000
。
Solution
Code
#include <iostream>
#include <cstdio>
#define LL long long
#define MOD 1000000007
using namespace std;
LL n,m,ans=1;
LL jie[1000010];
LL ni[1000010];
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;
}
int main(){
freopen("indexone.in","r",stdin);
freopen("indexone.out","w",stdout);
scanf("%lld%lld",&n,&m);
if(m>n){printf("0\n");return 0;}
jie[0]=1;
for(LL i=1;i<=n;i++)jie[i]=jie[i-1]*i%MOD;
ni[n]=power(jie[n],MOD-2,MOD);ni[0]=1;
for(LL i=n-1;i>=1;i--)ni[i]=ni[i+1]*(i+1)%MOD;
ans=jie[n]*jie[n-1]%MOD*ni[n-m]%MOD;
printf("%lld\n",ans);
return 0;
}
INDEX2
【问题描述】
故事承接上文。
这事发生在博士还不那么内涵, 现哥还不那么傻逼, 姜嗲还没开始玩 dota, 巨胖才 50Kg的时候。
有一天, INDEX 的老婆再也不能忍受 INDEX 那过分庞大超过一阿伏伽德罗常数的后宫量, 那天夜里, 她将 INDEX 绑架到了飞船上, “私奔” 到了月球, 在 《Fly me to the moon》的歌声中。
好美啊!
这个时刻,INDEX 发现有一颗蓝色的星球一直在绕着一颗红色的星球转动。接着,他又发现,他的故乡火星也一直在绕着这颗红色的星球转动! ! !厉害爆了有木有! ! !现在,他的老婆将这颗蓝色星球命名为
A
,他们的故乡火星命名为
一开始的时间计算为
0
,在
A
的移动速度为
INDEX 向她老婆发誓, 他们会在月球上度过一段美好的二人时光, 直到到某个 INDEX 小时整点的钟声敲响时,若星球
A
和星球
思念自己庞大后宫团的 INDEX 想问你,他们启程返回火星的时刻。
【输入】
输入文件名为 Indextwo.in。
输入仅一行,包含五个正整数,分别为
L
,
【输出】
输出文件名为 Indextwo.out
输出仅一行,表示他们启程返回火星的时刻。若永远都不存在那个时刻,请输出“Ohahahahahahaha” ,不包含双引号。
【输入样例】
3 1 1 2 2
【输出样例】
0
【数据范围】
对于
30%
的数据,保证有
1≤L≤100
。
对于
100%
的数据,保证有
1≤L≤1000000
,而且
0≤Sa,Sb≤L−1
,
1≤Va,Vb≤L
。
Solution
问题等价于求
即
得
用扩展欧几里得定理即可求出一个解 x0 ,然后得出通解:
求出最小正整数解即可。
Code
#include <iostream>
#include <cstdio>
#define LL long long
#define Min(x,y) ((x)<(y)?(x):(y))
using namespace std;
LL l,sa,sb,va,vb;
LL x,y,fx,fy,fxx,fyy;
LL ex_gcd(LL a,LL b,LL &fx,LL &fy){
if(b==0){fx=1;fy=0;return a;}
LL fa,fb;
LL c=ex_gcd(b,a%b,fa,fb);
fx=fb;
fy=fa-fb*(a/b);
return c;
}
int main(){
freopen("indextwo.in","r",stdin);
freopen("indextwo.out","w",stdout);
scanf("%lld%lld%lld%lld%lld",&l,&sa,&sb,&va,&vb);
if(va<vb){swap(va,vb);swap(sa,sb);}
if(sa==sb){printf("0\n");return 0;}
LL Gcd=ex_gcd(va-vb,l,x,y);
if((sb-sa)%Gcd!=0){printf("Ohahahahahahaha\n");return 0;}
LL bd=l/Gcd;
x*=((sb-sa)/Gcd);
x=(x%bd+bd)%bd;
printf("%lld\n",x);
return 0;
}
INDEX3
【问题描述】
故事承接上文。
INDEX 回家之后,果断废弃了他的后宫基友团。开始和他老婆移居到农村,在一个
N
行
特别的,在原点那里,有一个 INDEX 造的太阳。
然而,这次种植的树木名字叫做超能树, 为啥叫超能呢, 因为它超需要能量, 所以叫做超能树, 如果这棵树无法从 INDEX 造的太阳中获得能量,也就是有其它树挡住了它的阳光,它就会死去。
一棵树挡住了另一棵树当且仅当这两棵树与原点三点共线,且一棵树距离原点更近。
INDEX 已经种植了在他的土地上的每个整点上都种植了一棵超能树。
INDEX 想知道,有多少树可以活下来?
【输入】
输入文件名为 Indexthree.in。
输入仅一行,包含两个正整数
N
和
【输出】
输出文件名为 Indexthree.out。
输出仅一行,表示最后活下来的树木个数。
【输入样例】
2 2
【输出样例】
3
【样例解释】
(2,2) 上的树被 (1,1) 上的树挡住了,所以只有两棵树成活。
【数据范围】
对于
60%
的数据,保证有
1≤N,M≤1000
。
另外
20%
的数据,保证
N=M
。
对于
100%
的数据,保证有
1≤N,M≤1000000
。
Solution
易知,
(x,y)
上的树不被其它树挡住的充要条件是
gcd(x,y)=1
。
因为若
gcd(x,y)=d
,
d>1
,那么
(x,y)
上的树必会被
(xd,yd)
上的树挡住。
所以,问题转化为:对于给定的整数
a
,
用莫比乌斯反演即可解决,具体实现方法请见我的另一篇博客 Zap。
Code
#include <iostream>
#include <cstdio>
#define LL long long
#define Min(x,y) ((x)<(y)?(x):(y))
using namespace std;
LL n,m,ans;
LL prime[1000010];
bool no_prime[1000010];
LL mu[1000010];
LL sum[1000010];
int main(){
freopen("indexthree.in","r",stdin);
freopen("indexthree.out","w",stdout);
scanf("%lld%lld",&n,&m);
if(n>m)swap(n,m);
mu[1]=sum[1]=1;
for(LL i=2;i<=n;i++){
if(!no_prime[i]){prime[++prime[0]]=i;mu[i]=-1;}
for(LL j=1;prime[j]*i<=n;j++){
no_prime[i*prime[j]]=true;
if(i%prime[j]==0){mu[i*prime[j]]=0;break;}
mu[i*prime[j]]=-mu[i];
}
sum[i]=sum[i-1]+mu[i];
}
for(LL i=1,it;i<=n;i=it+1){
it=Min(n/(n/i),m/(m/i));
ans=ans+(n/i)*(m/i)*(sum[it]-sum[i-1]);
}
printf("%lld\n",ans);
return 0;
}