LOJ #2023. 「AHOI / HNOI2017」抛硬币(组合计数,拓展Lucas)

题目
有人讲得比我好
嗯,总的来说就是把情况通过反转每一位的值来建立一一映射。
建立映射之后就可以简单+不能建立映射的方案再/2了,
这个题对于2的逆元的处理十分巧妙,也可以当做一个不错的 e x L u c a s exLucas 板题。

A C   C o d e \mathrm {AC \ Code}

#include<bits/stdc++.h>
#define LL long long
#define mod 1000000000
#define rep(i,j,k) for(int i=(j);i<=(k);i++)
using namespace std;

void exgcd(int a,int b,int &x,int &y,int &gcd){ !b?(x=1,y=0,gcd=a):(exgcd(b,a%b,y,x,gcd),y-=a/b*x); }
struct factory{
	int fac[1953125],P,Pr;
	void init(int p,int pr){ fac[0]=1,P=p,Pr=pr;rep(i,1,p-1) fac[i]=i%pr?1ll*fac[i-1]*i%P:fac[i-1]; }
	int Pow(int b,int k){ int r=1;for(;k;k>>=1,b=1ll*b*b%P) if(k&1)r=1ll*r*b%P;return r; }
	int INV(int u){ int x,y,gd;exgcd(u,P,x,y,gd);return x; }
	int F(LL n){ return n?F(n/Pr)*1ll*fac[n%P]%P*Pow(fac[P-1],n/P)%P:1; }
	int C(LL n,LL m){
		int k=0;for(LL t=n;t;t/=Pr) k+=t/Pr;
		for(LL t=m;t;t/=Pr) k-=t/Pr;for(LL t=n-m;t;t/=Pr) k-=t/Pr;
		if(k >= 9) return 0;
		
		return 1ll * F(n) * INV(F(m)) % P * INV(F(n-m)) % P * Pow(Pr,k) % P;
	}
}f2,f5;
int C(LL n,LL m){
	int a=f2.C(n,m),b=f5.C(n,m),x,y,gd;
	exgcd(512,1953125,x,y,gd);
	return (a + 512ll * x % mod * (b-a)) % mod;
}
int Pow(int b,LL k){ int r=1;for(;k;k>>=1,b=1ll*b*b%mod) if(k&1) r=1ll*r*b%mod;return r; }
void print(int a,int k){ for(;k--;) printf("%d",a/Pow(10,k)%10);puts(""); }

int main(){
	LL a,b,k;
	f2.init(512,2),f5.init(1953125,5);
	for(;~scanf("%lld%lld%d",&a,&b,&k);){
		if(a == b) print((Pow(2,a+b-1)-C(2*a-1,a))%mod+mod,k);
		else{
			int ans = (Pow(2,a+b-1) + ((!((a+b)&1)) ? C(a+b-1,(a+b)/2) : 0)) % mod;
			rep(j,1,(a-b-1)/2) ans = (ans + C(a+b,b+j)) % mod;
			print((ans+mod)%mod,k);
		}
	}
}

发布了627 篇原创文章 · 获赞 91 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/qq_35950004/article/details/103683754