题目描述
There are N children in kindergarten. Miss Li bought them N candies。To make the process more interesting, Miss Li comes up with the rule: All the children line up according to their student number (1…N), and each time a child is invited, Miss Li randomly gives him some candies (at least one). The process goes on until there is no candy. Miss Li wants to know how many possible different distribution results are there.
输入
The first line contains an integer T, the number of test case.
The next T lines, each contains an integer N.
1 ≤ T ≤ 100
1 ≤ N ≤ 10^100000
输出
For each test case output the number of possible results (mod 1000000007).
样例输入
复制样例数据
1
4
样例输出
8
题意:老师有n个糖果,然后挨着分给n个同学,至少分一个,问分的方法数有多少种%1e9+7
很轻松可得递推公式:f(n)=f(0)+f(1)+f(2)......f(n-1) 将f(0)看为1;
答案即为pow(2,-1)%mod
先给出一个十进制快速幂T了的代码。。。。1300毫秒。
#include<bits/stdc++.h>
#include <iostream>
#include <algorithm>
#include <string>
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define pi acos(-1.0)
using namespace std;
ll a, mod=1e9+7;
const int maxx=1e6+100;
char s[maxx];
ll mpow ( ll a, ll b, ll mod )
{
ll rt;
for (rt=1;b;b>>=1)
{
if(b&1)
{
rt=rt*a;
if(rt>mod) rt%=mod;
}
a=a*a;
if(a>mod) a%=mod;
}
return rt;
}
ll kuaisumi(ll a,ll b)
{
ll ans=1;
while(b)
{
if(b&1)
{
ans=ans*a;
if(ans>mod) ans%=mod;
}
a=(a*a);
if(a>mod) a%=mod;
b>>=1;
}
return ans;
}
int main ()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf ("%s",s);
int len = strlen (s);
reverse(s,s+len);
//printf("%c\n",s[len-1]);
ll base = 2;
ll cur = 1;
for (int i = 0; i < len; i++) {
cur=cur*mpow(base,s[i]-'0',mod);
if(cur>mod) cur%=mod;
base=mpow(base,10,mod);
if(base>mod) base%=mod;
}
ll x=kuaisumi(2,mod-2);
cur=(cur*x)%mod;
printf ("%lld\n", cur);
}
}
这是一个能过的十进制快速幂
800mm
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define ri register int
#define ll long long
ll b,len,h,P,i,j;
const ll mod=1e9+7;
char c[100007];
ll kuaisumi(ll a)
{
ll ans=1,s=a;
while(len>=0)
{
ll cnt=c[len]-'0',cur=s;
for(ri i=1;i<=cnt;i++)
{
ans=(ans*s)%mod;
}
for(ri i=1;i<10;i++)
{
cur=(cur*s)%mod;
}
s=cur;
ans%=mod;
len--;
}
return ans;
}
ll niyuan(ll a,ll b)
{
ll ans=1;
while(b)
{
if(b&1)
{
ans=ans*a;
if(ans>mod) ans%=mod;
}
a=(a*a);
if(a>mod) a%=mod;
b>>=1;
}
return ans;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf ("%s",c);
len=strlen(c);
len--;
ll x=niyuan(2,mod-2);
ll ans=kuaisumi(2);
printf ("%lld\n",(x*ans)%mod);
}
return 0;
}
给出欧拉降幂的公式 :
pow(a,b)%mod=pow(a,b%ϕ(a)) %mod b>ϕ(a) && gcd(a,b)==1
然后给出一个欧拉筛的代码,ϕ(x)代表小于x的数中与x互质的个数;
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include <iostream>
#include<string.h>
#include<algorithm>
#define ll long long
#define hengheng main ()
using namespace std;
const int maxx=1e6+200;
int sushu[maxx];
bool biaoji[maxx];
ll i,j,m,n,k;
int cnt=0;
ll ola[maxx];
void olashai()
{
memset(biaoji,true,sizeof(biaoji));
for(i=2;i<maxx;i++)
{
if(biaoji[i]!=0)// 还未被标记
{
sushu[cnt]=i;
cnt++;
ola[i]=i-1;
}
for(j=0;j<cnt&&sushu[j]*i<maxx;j++) //用素数筛素数
{
biaoji[sushu[j]*i]=0; // 标记出素数的倍数
if(i%sushu[j]==0) //i是这个素数的倍数
{
ola[sushu[j]*i]=ola[i]*sushu[j];
break; //用一个素数筛到即可,如用素数2筛了14就不需要用7筛14了
}
else
ola[sushu[j]*i]=ola[i]*(sushu[j]-1);
}
}
}
int hengheng
{
olashai();
ola[1]=1;
for(i=2;i<=1000000;i++)
ola[i]+=ola[i-1];
while(scanf("%d",&n)!=EOF)
{
if(n==0) break;
printf("%lld\n",ola[n]);
}
return 0;
}
正解:
大数取余:就是一个模拟而已;
ll len=strlen(s);
ll ans = 0;//大数取余模板ll
for (int i = 0; i < len; ++i)
{
ans = ans * 10 + (s[i] - '0');
ans %= mod-1;
}
#include<bits/stdc++.h>
#include <iostream>
#include <algorithm>
#include <string>
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define pi acos(-1.0)
using namespace std;
ll a, mod=1e9+7;
const int maxx=1e6+100;
char s[maxx];
ll kuaisumi(ll a,ll b)
{
ll ans=1;
while(b)
{
if(b&1)
{
ans=ans*a;
if(ans>mod) ans%=mod;
}
a=(a*a);
if(a>mod) a%=mod;
b>>=1;
}
return ans;
}
int main ()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf ("%s",s);
ll len=strlen(s);
ll ans = 0;//大数取余模板ll
for (int i = 0; i < len; ++i)
{
ans = ans * 10 + (s[i] - '0');
ans %= mod-1;
}
printf("%lld\n",kuaisumi(2,ans-1));
}
}