题目背景
本题由世界上最蒟蒻最辣鸡最撒比的SOL提供。
寂月城网站是完美信息教室的官网。
题目描述
辣鸡蒟蒻SOL是一个傻逼,他居然觉得数很萌!
今天他萌上了组合数。现在他很想知道simga(C(n,i))是多少;其中C是组合数(即C(n,i)表示n个物品无顺序选取i个的方案数),i取从0到n所有偶数。
由于答案可能很大,请输出答案对6662333的余数。
输入输出格式
输入格式:
输入仅包含一个整数n。
输出格式:
输出一个整数,即为答案。
输入输出样例
3
4
说明
对于20%的数据,n <= 20;
对于50%的数据,n <= 1000;
对于100%的数据,n <= 1 000 000 000 000 000 000 (10^18)
题解:
关于二项式定理的的知识可浏览360百科中的:https://baike.so.com/doc/5409658-5647689.html
由二项式定理可得:C(n,0)+C(n,1)+C(n,2)+…+C(n,n-2)+C(n,n-1)+C(n,n)=2^n
由于题目上说i只取偶数(包括0)所以最后的结果是2^(n-1)。
用O(n)算法效率低会超时的。
剩下的就是快速幂了,可以用迭代写,也可以用递归,那得看个人习惯了。
快速幂用位运算写效率可能更高:
这是百度百科中比较好的快速幂位运算算法:
int pow(int a,int b){ int r=1,base=a; while(b){ if(b&1) r*=base; base*=base; b>>=1; } return r; }
百度百科中关于快速幂的讲解比较详细:https://baike.baidu.com/item/%E5%BF%AB%E9%80%9F%E5%B9%82
本题在做的过程中要取余,下面贴出个人代码:
递归:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; typedef long long ll; ll n; ll powmod(ll k,ll m) { if(k==0) return 1; ll x=powmod(k/2,m); ll ans=(x*x)%m; if(k%2) ans=(ans*2)%m; return ans; } int main() { scanf("%lld",&n); ll ans=powmod(n-1,6662333); printf("%lld\n",ans); return 0; }
非递归:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; typedef long long ll; ll n; ll powmod(ll a,ll b,ll c) { ll ans=1%c; a%=c; while(b) { if(b%2==1) ans=ans*a%c; b=b/2; a=a*a%c; } return ans; } int main() { scanf("%lld",&n); ll ans=powmod(2,n-1,6662333); printf("%lld\n",ans); return 0; }