2016 Multi-University Training Contest 6 解题报告

来源:互联网 发布:诺基亚 x311玩java 编辑:程序博客网 时间:2024/06/06 00:23

1. 1001-HDU 5793 A Boring Question

题意:给定n,m,求的值。其中


题解:

二项式定理:


特别的,


即,


其中


所以:


用快速幂来求解m^(n+1)由于要取模,但是有除法所以用费马小定理可得:a / c mod p== a * c^(p-2) mod p。

代码:

#include <iostream>#include <algorithm>#include <cstdio>using namespace std;const int MOD=1000000007;typedef long long LL;LL Pow(LL a,LL n){    LL ans=1;    while(n){        if(n&1)ans=ans*a%MOD;        n>>=1;        a=a*a%MOD;    }    return ans;}int main(){    int T;    scanf("%d",&T);    while(T--)    {        LL n,m;        scanf(" %I64d %I64d",&n,&m);        printf("%I64d\n",(Pow(m,n+1)-1)*Pow(m-1,MOD-2)%MOD);    }    return 0;}

2. 1002- HDU 5794 A Simple Chess

题意:一个n*m的棋盘,一个棋子想从(1,1)走到(n,n),棋子每步可从(x1,y1)到达(x2,y2),

当且仅当

另外,棋盘上有r处障碍,棋子无法到达障碍处,问棋子从(1,1)到达(n,m)有多少种走法?

题解:


根据题意,棋子只能走(x+1,y+2)①或者(x+2,y+1)②这两个方向 ,所以只有满足一定条件的位置才有可能到达。我们假设①方向走了a步,②方向走了b步,那么我们可以得到满足条件的位置一定是x=a+2b,y=2a+b,所以可以得到只有(x+y)是3的整数倍的位置才有可能到达。并且(1/2<=y/x<=2)

我们先不考虑障碍物,则到达每个点的方案数构成一个杨辉三角,即每个点的方案数等于它两肩上的数之和。我们可以用坐标计算出这个点在杨辉三角中的 位置。杨辉三角第x行第y列(x,y下标均从0开始)的数为组合数C(x,y),大数组合数用Lucas定理。

然后考虑障碍物,到达终点的方案数等于(不考虑障碍物的方数)-(起点到障碍物的方案数)*(障碍物到终点的方案数),而(起点到障碍物的方案数)的计算也要减去其他障碍物对它的影响

代码 :

#include <iostream>#include <cstdio>#include <algorithm>using namespace std;const int MAX=100+5;const int MOD=110119;typedef long long LL;struct node{    LL x,y,val;    node(LL _x=0,LL _y=0,LL _val=0):x(_x),y(_y),val(_val) {};    bool operator <(const node &a) const    {        return this->x<a.x||(this->x==a.x&&this->y<a.y);    }} ob[MAX];LL f[200000];void init(int p){    f[0] = 1;    for(int i = 1; i <= p; ++i)        f[i]  = f[i-1] * i % p;}LL pow_mod(LL a, LL x, int p){    LL ret = 1;    a %= p;    while(x)    {        if(x & 1)        {            ret = ret * a % p;            --x;        }        else        {            a = a * a % p;            x >>= 1;        }    }    return ret;}LL Lucas(LL n, LL k, int p){    LL ret = 1;    while(n && k)    {        LL nn = n % p, kk = k % p;        if(nn < kk) return 0;        ret = ret * f[nn] * pow_mod(f[kk] * f[nn - kk] % p, p - 2, p) % p;        n /= p;        k /= p;    }    return ret;}LL waycnt(LL x1,LL y1,LL x2,LL y2,int p){    LL x=x2-x1;    LL y=y2-y1;    if((x1+y1)%3!=2) return 0;    if((x2+y2)%3!=2) return 0;    if((x+y)%3!=0) return 0;    LL row=(x+y)/3;    LL col=x-row;    if(col<0||col>row) return 0;    return Lucas(row,col,p);}int main(){    init(MOD);    int tcase=1;    LL n,m,r;    while(cin>>n>>m>>r)    {        for(int i=0; i<r; i++)        {            cin>>ob[i].x>>ob[i].y;        }        sort(ob,ob+r);        for(int i=0; i<r; i++)        {            ob[i].val=waycnt(1,1,ob[i].x,ob[i].y,MOD);            for(int j=0; j<r; j++)            {                if(ob[j].x<ob[i].x&&ob[j].y<ob[i].y)                    ob[i].val=((ob[i].val-(ob[j].val*waycnt(ob[j].x,ob[j].y,ob[i].x,ob[i].y,MOD)%MOD))%MOD+MOD)%MOD;            }        }        LL ans=waycnt(1,1,n,m,MOD);        for(int i=0; i<r; i++)        {            if(ob[i].x==n&&ob[i].y==m)            {                ans=0;                break;            }            if(ob[i].x<n&&ob[i].y<m)                ans=((ans-(ob[i].val*waycnt(ob[i].x,ob[i].y,n,m,MOD)%MOD))%MOD+MOD)%MOD;        }        printf("Case #%d: %I64d\n",tcase++,ans);    }    return 0;}

3. 1010-HDU 5802 Windows 10

题意:windows 10 调音量。

按up键可以往上调高一个DB,按down键可以向下调x个DB,如果上一次是按的up键或者上一次是停止,x=1,如果上次按的是down键,且向下降了xDB,则x=2*x。要求从p调到q,最少需要多少次按键?

题解:

显然,如果p<=q,则只能一次一次向上调,答案为q-p;

如果p>q,那么最少的步数为:

一直指数下降,下降到大于q的最小的那个数,然后停一次,再继续指数下;

或者下降到小于q的最大的那个数,然后在向上升回去。

比较两种情况所需的步数,取最小值。

需要注意的是:

1. 音量不能小于0;

2. 由于up和停止都可以使得x变为1,所以可以在用上升来抵消停顿,即在需要停一次的时候向上升1DB,这样可以使得下降到比q小时少上升几次。

代码:

#include <iostream>#include <algorithm>#include <cstdio>using namespace std;typedef long long LL;LL dfs(LL s,LL t,LL step,LL rest){    if(s==t) return step;    LL x=0;    while(s-(1<<x)+1>t) x++;    if(s-(1<<x)+1==t) return step+x;    LL up=t-max(s-(1<<x)+1,0ll);    return min(step+x+max(0ll,up-rest),dfs(s-(1<<(x-1))+1,t,step+x,rest+1));}int main(){    int T;    scanf("%d",&T);    while(T--)    {        int p,q;        scanf("%d%d",&p,&q);        if(p<=q) printf("%d\n",q-p);        else printf("%I64d\n",dfs(p,q,0,0));    }    return 0;}


0 0
原创粉丝点击