牛客小白月赛14 -A (找规律+除数取模)

题目链接:https://ac.nowcoder.com/acm/contest/879/A

题意:有n个城市,编号1~n,k天,第一天位于城市1,要求最后一天在城市1,且相邻两天不在同一个城市,求方案数。

思路:设k天后在城市1的方案数为f(k),前k-1天每天有n-1种选择,最后一天必须去城市1,即有(n-1)^(k-1)种可能,但是这包括了倒数第二天在城市1的情况。但我们会发现倒数第二天在城市1的方案数即f(k-1),即f(k)=(n-1)^(k-1)-f(k-1)。

  不访列举前几项:

    f(k=1)=0

    f(k=2)=n-1

    f(k=3)=(n-1)^2-f(k=2)=(n-1)^2-(n-1)

    f(k=4)=(n-1)^3-f(k-3)=(n-1)^3-(n-1)^2+(n-1)

  可以发现每一项均是等比数列的求和等式。于是有f(k)=[(-1)k*(n-1)+(n-1)k]/n。

  要将这个式子对MOD=998244353取模,需要用到公式a/b%m=a%(b*m)/b。

AC代码:

#include<cstdio>
using namespace std;
typedef long long LL;
const LL MOD =998244353;

LL n,k,M;

LL qmul(LL a,LL b){
    LL ret=0;
    while(b){
        if(b&1) ret=(ret+a)%M;
        a=(a+a)%M;
        b>>=1;
    }
    return ret;
}

LL qpow(LL a,LL b){
    LL ret=1;
    while(b){
        if(b&1) ret=qmul(ret,a);
        a=qmul(a,a);
        b>>=1;
    }
    return ret;
}

int main(){
    scanf("%lld%lld",&n,&k);
    M=n*MOD;
    if(k&1)
        printf("%lld\n",(M-n+1+qpow(n-1,k))%M/n);
    else
        printf("%lld\n",(n-1+qpow(n-1,k))%M/n);
    return 0;
}

 

posted @ 2019-05-12 14:11  Frank__Chen  阅读(379)  评论(0编辑  收藏  举报