【计蒜客】2018ICPC焦作赛区网络赛G Give Candies(小费马定理+快速幂)

题目链接

【题意】

有n个小朋友,排队从老师手中领取n个糖,先到的小朋友先得到若干个糖,直到糖分完,输出有几种分配方式。

 

【解题思路】

规律很好找,就是(2^n-1)%p,但是n太大了,需要用费马小定理转换一下。

费马小定理:若gcd(a,p)=1,那么a^{p-1} \equiv 1(mod )p

为了构造一个p-1,使n-1=k(p-1)+m,那么原式即等于2^(n-1)%p=2^k(p-1)%p*2^m%p,即2^(n-1)%p=2^m%p

又因为m=(n-1)%(p-1),所以只需求出m即可。

用字符串输入n,需要做一下预处理,若最后一位>0,直接减1即可,若等于0,需要向高位借位,然后再将字符串转换成整数,边转换边跟p-1取余,最后用快速幂求解。

 

【代码】

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int mod=1e9+6;
const int MOD=1e9+7;
char s[100005];
LL quickpow(LL a,LL b)
{
    LL ans=1;
    while(b)
    {
        if(b&1)ans=ans*a%MOD;
        a=a*a%MOD;
        b>>=1;
    }
    return ans%MOD;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%s",s);
        if(s=="1")
        {
            printf("1\n");
            continue;
        }
        int l=strlen(s),pos;
        if(s[l-1]>'0')s[l-1]--;
        else
        {
            s[l-1]='9';
            pos=l-2;
            while(s[pos]=='0')
            {
                s[pos]='9';
                pos--;
            }
            s[pos]--;
        }
        LL a=0;
        for(int i=0;i<l;i++)
        {
            a=a*10+(s[i]-'0');
            a=a%mod;
        }
        LL ans=quickpow(2,a);
        printf("%lld\n",ans%MOD);
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值