简单数学(组合数+求数列通项公式)
程序员文章站
2023-10-31 18:54:10
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6467 看到这题,简单数学???对不起我给数学老师丢脸了! 这里解释一下第二步到第三步:假设n=3,第二步{1*C(1,1)+1*C(1,2)+1*C(1,3)+2*C(2,2)+2*C(2,3)+3*C ......
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6467
看到这题,简单数学???对不起我给数学老师丢脸了!
这里解释一下第二步到第三步:假设n=3,第二步{1*c(1,1)+1*c(1,2)+1*c(1,3)+2*c(2,2)+2*c(2,3)+3*c(3,3)},第三步{1*c(1,1)+1*c(1,2)+2*c(2,2)+1*c(1,3)+2*c(2,3)+3*c(3,3)}。可以发现是相等的
之后最后一步就是组合数求和公式2^n。
之后便可以得到递推公式。但是直接用递推公式写还是会超时的,所以要进一步化简成通项公式。
n*(2^(n-1))=2(n-1)*(2^(n-1))-(n-2)*(2^(n-1))
之后根据这个将其分配
f(n)-(n-1)*2^n=f(n-1)-(n-2)*(2^(n-1))
很明显就有等比数列:(f(n)-(n-1)*2^n)/(f(n-1)-(n-2)*(2^(n-1)))=1
并且这个等比数列的公比就是1
而f(1)=1,所以第一项值为1
所以很明显这个等比数列恒为1
所以f(n)-(n-1)*2^n=1 --->f(n)=(n-1)*(2^n)+1
既然有了通项公式,ac什么的都太简单了。
#include <bits/stdc++.h> using namespace std; #define re register #define ll long long const ll mod=1e9+7; void read(int &a) { a=0; int d=1; char ch; while(ch=getchar(),ch<'0'||ch>'9') if(ch=='-') d=-1; a=ch-'0'; while(ch=getchar(),ch>='0'&&ch<='9') a=a*10+ch-'0'; a*=d; } void write(int x) { if(x<0) putchar(45),x=-x; if(x>9) write(x/10); putchar(x%10+'0'); } ll quickmod(ll x,ll y) { ll res=1; ll base=x; while(y) { if(y&1) res=res*base%mod; base=base*base%mod; y>>=1; } return res; } int main() { ll n; while(~scanf("%lld",&n)) { ll ans=((((n-1)%mod*quickmod(2,n))%mod)+1)%mod; printf("%lld\n",ans); } return 0; }