您的位置:首页 > 其它

HDU 4704 Sum

2017-08-19 15:30 218 查看
题意为: 将n(小于等于10的十万次方),分别拆成1个数,2个数...n个数的方案和。

由插板法我们可以知道,每一个问题可以看做有n个球,需要插入(i-1)个板的答案。即从n-1个空里面找i-1个位置来

插板的方案数,即C(i-1,n-1),由组合数的求和我们便可以知道,这个问题的答案就是求和C(0~n-1,n-1),答案

即为2的n-1次方。数据过大,我们可以使用费马小定理进行降幂,或者使用十进制快速幂来完成。

下附AC代码。

#include<iostream>
#include<string.h>
#define maxn 100005
using namespace std;
const long long  MOD=1e9+7;
long long quickmul(long long n,long long k)
{
long long ans=0;
while(k)
{
if(k&1)
{
ans=(ans+n)%MOD;
}
n=(n+n)%MOD;
k=k>>1;
}
return ans;
}
long long quickpow(long long n,long long k)
{
long long ans=1;
while(k)
{
if(k&1)
{
ans=quickmul(ans,n);
}
n=quickmul(n,n);
k=k>>1;
}
return ans;
}
long long quickpowbaseon10(long long n,string s)
{
long long ans=1;
long long powVal[10];
powVal[0]=1;
for(int i=1;i<=9;i++)
{
powVal[i]=quickmul(powVal[i-1],n);
}
for(int i=0,t=s.size();i<t;i++)
{
ans=quickmul(ans,powVal[s[i]-'0']);
if(i!=t-1)
{
ans=quickpow(ans,10);
}
}
return ans%MOD;
}
int a[maxn],b[maxn],c[maxn];
int main()
{
string s;
string j="1";
while(cin>>s)
{
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
int lena=s.size(),lenb=j.size();
for (int i=0;i<=lena-1;i++)
a[lena-i]=s[i]-'0';
for (int i=0;i<=lenb-1;i++)
b[lenb-i]=j[i]-'0';

int now=1;
while (now<=lena)
{
if (a[now]<b[now])
{
a[now]+=10;
a[now+1]--;
}
c[now]=a[now]-b[now];
now++;
}
for (int i=now;i>=1;i--)
if ((c[i]==0)&&(now>1))
now--;
else break;

string ans="";
for (int i=now;i>=1;i--)
{
ans+=(c[i]+'0');
}
cout<<quickpowbaseon10(2,ans)<<endl;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: