ACM-ICPC 2018 焦作赛区网络预赛 G. Give Candies (打表找规律+快速幂)
Posted zjl192628928
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ACM-ICPC 2018 焦作赛区网络预赛 G. Give Candies (打表找规律+快速幂)相关的知识,希望对你有一定的参考价值。
题目链接:https://nanti.jisuanke.com/t/31716
题目大意:有n个孩子和n个糖果,现在让n个孩子排成一列,一个一个发糖果,每个孩子随机挑选x个糖果给他,x>=1,直到无糖果剩余为止。给出数字n,问有多少种分发糖果的方法。
样例输入
1
4
样例输出
8
解题思路:我们可以这样想,一个糖果的话,应该是只有1种方法记为x1,如果是两个糖果的话,有两种方法即为x2,分别为(1,1)和(2),从中我们可以想到如果n个糖果的话,就可以分为第n个人取1个的话就有x(n-1)种,去两个的话就有x(n-2)种,依次类推,第n个人取n-1个的话就有x1种方法,第n个人取n个的话就只有1种方法。即x(n)=x1+x2+……+x(n-1)+1=2^(n-1);
其实就是一个简单的拆数问题,比如这里有三个学生,老师有三个糖果,有四种分法:{3,0,0},
{2,1,0},{1,2,0},{1,1,1}
一个数的拆法其实就是2^(N-1)
也可以打表找规律,都很简单。
但是有一个难点是n的范围特别大,可以达到10^100000,不能通过整型数字存储,而只能用字符数组存储这个数,这样的话我们肯定不能直接用快速幂。所以这里就要采用一个小技巧,也就是一个性质,2^N模一个质数,它的结果是具有周期性的,周期长度为mod-1,这道题就利用这个周期
性质,具体步骤就是:先把n转化成模mod-1下的的数,然后用这个数计算快速幂。
附上代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod=1e9+7;
char s[100005];
ll qpow(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--)
{
scanf("%s",s);
int len=strlen(s);
ll MOD=mod-1,temp=0;
for(int i=0;i<len;i++)
temp=(temp*10+s[i]-‘0‘)%MOD; //将n转化成mod-1内的数
if(temp==0) temp=MOD; //特判temp==0时,temp即为mod-1
temp=(temp-1+MOD)%MOD;
ll ans=qpow(2,temp);
cout<<ans<<endl;
}
return 0;
}
以上是关于ACM-ICPC 2018 焦作赛区网络预赛 G. Give Candies (打表找规律+快速幂)的主要内容,如果未能解决你的问题,请参考以下文章
ACM-ICPC 2018 焦作赛区网络预赛 B题 Mathematical Curse