数学测试3(test20170311pm)

【INDEX1】(Indexone.pas/c/cpp Time:1s Memory:256M)

【问题描述】

INDEX 是谁?兄弟,这个问题你如果不知道我就只能怀疑你是从火星来的了。 但是,如果你真的不知道他是谁,那么,你可能和他拥有同一个故乡。 其实当年 INDEX 在火星上有 N 个基友和 M 个妹子,生活真是非常逍遥。他每天都把 基友和妹子排成一队,使得他能够站在最前面,领着他的基友后宫团游街(囧)。 但是,他的妹子们的嫉妒心是很强的,如果两个妹子站在一起,肯定会为 INDEX 吵得 不可开交。同时,INDEX 也是有老婆的人,他身后,也就是队伍的第一个人必须是他的基 友后宫团的团长——他老婆(也就是说,M 个妹子中有一个是他的老婆,为了使题目容易 理解,也就是第一个人已经确定是 M 个妹子中的一个了)。而且,他希望由一个基友来殿后。 现在 INDEX 想知道,他能够排成多少种不同的队伍,使得这个队伍满足他的要求?

【输入】

输入文件名为 Indexone.in。 输入一行包含两个整数 N 和 M。

【输出】

输出文件名为 Indexone.out。 输出一行,表示合法的队伍总数对 1000000007 的模值,如果不存在何方方案则输出 0

【输入输出样例】

Indexone.in

1 1

Indexone.out

1

【数据范围】

对于 30%的数据,保证有1≤N,M≤1000。

对于另外 30%的数据,保证有1≤M≤10。

对于 100%的数据,保证有1≤N,M≤1000000。

【题解】

这个题其实和那个什么01序列差不多,答案:

ans=n!×pm1n1(modp)

【代码】

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;

typedef long long LL;
const int MOD = 1000000007;
const int size = 1000010;
LL a[size],b[size];
LL n,m,ans=1;

LL ksm(LL,LL,LL);

int main() {
    freopen("indexone.in","r",stdin);
    freopen("indexone.out","w",stdout);
    scanf("%lld%lld",&n,&m);
    if(m>n)
        return puts("0"),0;
    a[0]=1;
    for(LL i=1;i<=n;i++)
        a[i]=a[i-1]*i%MOD;
    b[n]=ksm(a[n],MOD-2,MOD);
    b[0]=1;
    for(LL i=n-1;i>=1;i--)
        b[i]=b[i+1]*(i+1)%MOD;
    ans=a[n]*a[n-1]%MOD*b[n-m]%MOD;
    printf("%lld\n",ans);
    return 0;
}

LL ksm(LL x,LL y,LL Mod) {
    x%=Mod;
    LL ret=1;
    while(y) {
        if(y&1)
            ret=ret*x%Mod;
        x=x*x%Mod;
        y>>=1;
    }
    return ret;
}

【INDEX2】(Indextwo.pas/c/cpp Time:1s Memory:256M)

【问题描述】

故事承接上文。 这事发生在博士还不那么内涵,现哥还不那么傻逼,姜嗲还没开始玩 dota,巨胖才 50Kg 的时候。有一天,INDEX 的老婆再也不能忍受 INDEX 那过分庞大超过一阿伏伽德罗常数的 后宫量,那天夜里,她将 INDEX 绑架到了飞船上,“私奔”到了月球,在《Fly me to the moon》 的歌声中。好美啊! 这个时刻,INDEX 发现有一颗蓝色的星球一直在绕着一颗红色的星球转动。接着,他 又发现,他的故乡火星也一直在绕着这颗红色的星球转动!!!厉害爆了有木有!!!现在,他 的老婆将这颗蓝色星球命名为 A,他们的故乡火星命名为 B,并将他们的轨道平均分成 L 块,形成了 L 块扇形区域吗,并从 0 到 L-1 逆时针标号,A 星球和 B 星球都是沿逆时针绕 红色星球转动。一开始的时间计算为 0,在 0 时刻时,A 处在 Sa 块,B 处在 Sb 块。A 的移 动速度为 Va 块每 INDEX 小时,B 的移动速度为 Vb 块每 INDEX 小时。INDEX 向她老婆发 誓,他们会在月球上度过一段美好的二人时光,直到到某个 INDEX 小时整点的钟声敲响时, 若星球 A 和星球 B 所在块的编号相同,那么,他们启程返回火星。 思念自己庞大后宫团的 INDEX 想问你,他们启程返回火星的时刻。

【输入】

输入文件名为 Indextwo.in。 输入仅一行,包含五个正整数,分别为 L,Sa,Sb,Va,Vb。

【输出】

输出文件名为 Indextwo.out 输出仅一行,表示他们启程返回火星的时刻。若永远都不存在那个时刻,请输出 “Ohahahahahahaha”,不包含双引号。

【输入输出样例】

Indextwo.in

3 1 1 2 2

Indextwo.out

0

【数据范围】

对于 30%的数据,保证有 1≤L≤100。

对于 100%的数据,保证有 1≤L≤1000000,而且 0≤Sa,Sb≤L-1,1≤Va,Vb≤L。

【题解】

我们可以发现问题可以转化为求Sa+VaxSb+Vbx(modl) 的最小整数解。
可以转化为x(VaVb)lk=SbSa
此时可以很明显发现用扩展gcd就可以求出一个解,那么求通解就很简单了。而我们只要当中的最小整数解。
【代码】

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;

typedef long long LL;
LL l,sa,sb,va,vb;
LL x,y;

void swap(int &a,int &b) {
    a^=b;b^=a;a^=b;
}

LL ex_gcd(LL a,LL b,LL &x,LL &y) {
    if(b==0) {
        x=1;y=0;
        return a;
    }
    LL ret=ex_gcd(b,a%b,y,x);
    y-=x*(a/b);
    return ret;
}

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)
        return puts("0"),0;
    LL Gcd=ex_gcd(va-vb,l,x,y);
    if((sb-sa)%Gcd!=0)
        return puts("Ohahahahahahaha"),0;
    LL bd=l/Gcd; 
    x*=((sb-sa)/Gcd);
    x=(x%bd+bd)%bd;
    printf("%lld\n",x);
    return 0;
}

【INDEX3】(Indexthree.pas/c/cpp Time:1s Memory:256M)

【问题描述】

故事承接上文。 INDEX 回家之后,果断废弃了他的后宫基友团。开始和他老婆移居到农村,在一个 N 行 M 列的土地上,在平面直角座标系中,就是横座标从 1 到 N,纵座标从 1 到 M 的地方上 种植树木。特别的,在原点那里,有一个 INDEX 造的太阳。然而,这次种植的树木名字叫 做超能树,为啥叫超能呢,因为它超需要能量,所以叫做超能树,如果这棵树无法从 INDEX 造的太阳中获得能量,也就是有其它树挡住了它的阳光,它就会死去。一棵树挡住了另一棵 树当且仅当这两棵树与原点三点共线,且一棵树距离原点更近。INDEX 已经种植了在他的 土地上的每个整点上都种植了一棵超能树。INDEX 想知道,有多少树可以活下来?

【输入】

输入文件名为 Indexthree.in。 输入仅一行,包含两个正整数 N 和 M。

【输出】

输出文件名为 Indexthree.out。 输出仅一行,表示最后活下来的树木个数。

【输入输出样例】

Indexthree.in

2 2

Indexthree.out

3

【样例解释】

(2,2)上的树被(1,1)上的树挡住了,所以只有两棵树成活。

【数据范围】

对于 60%的数据,保证有 1≤N,M≤1000。

另外 20%的数据,保证 N=M。

对于 100%的数据,保证有 1≤N,M≤1000000。

【题解】

易知,(x,y) 上的树不被其它树挡住的充要条件是gcd(x,y)=1。
因为若gcd(x,y)=d,d>1,那么 (x,y) 上的树必会被(x/d,y/d) (注:不知为何公式gg了)上的树挡住。
所以,问题转化为:对于给定的整数 a , b,有多少正整数对 (x,y),满足x≤a,y≤b,并且gcd(x,y)=1。

前60分,直接gcd(i,j)==1判断即可(暴力分真多)

后20分,用欧拉函数搞一下就可以了。

最后20分,据说要莫比乌斯反演。(然而并不会)

【代码】

先给上蒟蒻的60分暴力代码

#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long LL;

LL gcd(LL a,LL b) {
    return b?gcd(b,a%b):a;
}

LL n,m,ans=0;

int main() {
    freopen("indexthree.in","r",stdin);
    freopen("indexthree.out","w",stdout);
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;i++) {
        for(int j=1;j<=m;j++) {
            if(gcd(i,j)==1)
                ans++;
        }
    }
    printf("%lld\n",ans);
    return 0;
}

总结

这次考试竟然没有炸,真的神啦,会做的竟然没有炸,太神了!!!

发布了39 篇原创文章 · 获赞 7 · 访问量 1万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章