2018ACM-ICPC焦作网络赛 G.Give Candies

 

 

传送门

题意:

N个糖,N个人,一个人可能有多块糖也可能一个也没有,问有多少种分法。

思路:

用隔板法的思想,n个隔板代表N个糖被分成n+1堆,即分给n+1个人,那么让n的范围是1~N-1。二项式定理,c(n-1,0)+c(n-1,1)+……+c(n-1,n-1)=2^(n-1) 。所以只要输出2的n-1次方对mod=1000000007取模就好了。关键是n很大很大啊。网上的通用解法是欧拉函数降幂,费马小定理。可我比赛的时候还不会。。。机制的我,通过打表找到了500000003这个神奇的数字。(2^500000003 )%mod==1。 1乘任何数都不影响嘛,所以我让N对500000003取模后的结果作为真正的N,再2^(N-1) %mod 就是结果啦。

费马小定理 (a^n)%mod,如果mod为质数,a^(n%(mod-1))%mod

500000003*2=1000000006=mod-1    我在比赛的时候发现了费马小定理????

奇怪方法的奇怪AC代码如下(第二份是欧拉降幂):

#include
#include
#include
#include
#include
#include
#include 
const long long mod=1000000007;
typedef long long ll;
using namespace std;
char mi[100009];

ll FastM(ll a, ll p, ll  m)
{
    if (p == 0) return 1;
    ll r = a % m;
    ll k = 1;
    while (p)
    {
        if ((p & 1)!=0;
            k = (k * r) % m;
        r = (r * r) % m;
        p >>= 1;
    }
    return k % m;
}


int main()
{
    int t;cin>>t;
    //500,000,003
    while(t--)
    {
        long long m=0,ten=1;
        scanf("%s",mi);
        int len=strlen(mi);
        m=mi[0]-'0';
        if(len==1) {printf("%d\n",FastM(2,m-1,mod));continue;}
        for(int i=1;i
#include
#define rep(i,j,k) for(int i=j;i>=1;
    }
    return ans;
}
int main(void)
{
    IO
    int T;cin>>T;
    while(T--)
    {
        string s;
        cin>>s;
        ll p=0;
        rep(i,0,s.length())
        {
            p=(p*10+s[i]-'0')%(mod - 1);
        }
        cout<

 

你可能感兴趣的:(数论)