题目链接
题意:
给定一个数n 将其分解,Si 表示将n拆成i个数的方案数
求sum( si ) 1<=i<=n;
分析:
隔板原理, n个木棍,n-1个缝,
分成1份则是C(n-1,0);
分成2份则是C(n-1,1);
分成3份则是C(n-1,2);
...
分成n份则是C(n-1,n-1);
ans = sum( C(n-1,i) ) (0<=i<=n-1)
=2^(n-1);
由于要取模 而且 2 与 mod 互质 ,因此可以用费马小定理来降幂
费马小定理
若p是素数,a是正整数且不能被p整除,则:a^(p-1) ≡1(mod p)
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
typedef long long LL;
const int mod = 1e9+7;
const int max1 = 1e5+10;
char s[max1];
/*
LL quick_pow(LL m,LL n)
{
LL ans=1;
while(n){
if(n&1)
ans=(ans*m)%mod;
n=n>>1;
m=(m*m)%mod;
}
return ans;
}*/
LL quick_pow(LL a, LL b)
{
LL res = 1;
while (b != 0)
{
if (b & 1)
{
res = (res * a) % mod; //<span style="color:#ff0000;">不能写成res *= a % mod;</span>
}
b >>= 1;
a = a * a % mod;
}
return res % mod;
}
LL change(char s[], int m)
{
LL ans = 0;
int len = strlen(s);
for (int i = 0; i < len; i++)
{
ans = (ans * 10 + s[i] - '0') % m; //<span style="color:#ff0000;">注意是对mod-1取模的</span>
}
return ans;
}
int main()
{
while ((scanf("%s", s)) != EOF)
{
int m = mod - 1; //<span style="color:#ff0000;">注意n的值</span>
LL n = change(s, m);
printf("%I64d\n", quick_pow(2, (n - 1 + m) % m));
}
return 0;
}
参考博客:
HDU4869:Turn the pokers(费马小定理+快速幂)
搜索
复制