1. 程式人生 > 其它 >HHHOJ #666. 「NOIP2021模擬賽 By CQY C」相愛(loved)

HHHOJ #666. 「NOIP2021模擬賽 By CQY C」相愛(loved)

題面傳送門
真 十二重計數法弱化版。
這裡就講一下8,9
8的話隨便推一下就是\((^{n-1}_{m-1})\)
但是\(n,m\leq 10^9\)的範圍顯然不可行。
我們發現模數等於\(3*10007*35617\),然後可以Lucas之後中國剩餘定理合併。
9的話就是集合劃分數,有一個經典的dp:設\(dp_{i,j}\)表示\(i\)個數分成\(j\)份,那麼有\(dp_{i,j}=dp_{i,j-1}+dp_{i-j,j}\),一個是多分了一個0,另一個是將現有的所有都加上\(1\).
然後\(O(n^2)\)遞推就好了。
code:

#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define RI re int
#define ll long long
#define db double
#define lb long db
#define M 30000
#define mod 1000000007
#define eps (1e-4)
#define U unsigned int
#define it iterator
#define Gc() getchar() 
#define Me(x,y) memset(x,y,sizeof(x))
#define d(x,y) (n*(x-1)+(y))
#define R(n) (rand()*rand()%(n)+1)
#define Pc(x) putchar(x)
using namespace std;
struct IO{
    static const int S=1<<21;
    char buf[S],*p1,*p2;int st[105],Top;
    ~IO(){clear();}
    inline void clear(){fwrite(buf,1,Top,stdout);Top=0;}
    inline void pc(const char c){Top==S&&(clear(),0);buf[Top++]=c;}
    inline char gc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
    inline IO&operator >> (char&x){while(x=gc(),x==' '||x=='\n'||x=='\r');return *this;}
    template<typename T>inline IO&operator >> (T&x){
        x=0;bool f=0;char ch=gc();
        while(ch<'0'||ch>'9'){if(ch=='-') f^=1;ch=gc();}
        while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=gc();
        f?x=-x:0;return *this;
    }
    inline IO&operator << (const char c){pc(c);return *this;}
    template<typename T>inline IO&operator << (T x){
        if(x<0) pc('-'),x=-x;
        do{st[++st[0]]=x%10,x/=10;}while(x);
        while(st[0]) pc('0'+st[st[0]--]);return *this;
    }
}fin,fout;
int T,op;
I ll mpow(ll x,int y=mod-2){ll Ans=1;while(y) y&1&&(Ans=Ans*x%mod),y>>=1,x=x*x%mod;return Ans;}
namespace Solve1{
	int x,y;
	I void Make(){
		while(T--) fin>>x>>y,fout<<mpow(y,x)<<'\n';
	}
}
namespace Solve2{
	const int N=2e6;ll Inv[N+5],frc[N+5];int x,y;I void Make(){
		RI i;for(frc[0]=i=1;i<=N;i++)frc[i]=frc[i-1]*i%mod;Inv[N]=mpow(frc[N]);for(i=N-1;~i;i--) Inv[i]=Inv[i+1]*(i+1)%mod;
		while(T--)fin>>x>>y,fout<<(x>y?0:frc[y]*Inv[y-x]%mod)<<'\n';
	}
}
namespace Solve3{
	const int N=200000;int x,y;ll Inv[N+5],frc[N+5],Ans;I void Make(){
		RI i;for(frc[0]=i=1;i<=N;i++)frc[i]=frc[i-1]*i%mod;Inv[N]=mpow(frc[N]);for(i=N-1;~i;i--) Inv[i]=Inv[i+1]*(i+1)%mod;
		while(T--){
			fin>>x>>y;for(i=0;i<=y;i++) Ans+=(i&1?mod-frc[y]*Inv[i]%mod*Inv[y-i]%mod*mpow(y-i,x)%mod:frc[y]*Inv[i]%mod*Inv[y-i]%mod*mpow(y-i,x)%mod);printf("%lld\n",Ans%mod); 
		}
	}
}
namespace Solve4{
	const int N=5000;ll dp[N+5][N+5];int x,y;I void Make(){
		RI i,j;dp[0][0]=1;for(i=1;i<=N;i++){
			for(j=1;j<=N;j++) dp[i][j]=(dp[i-1][j-1]+dp[i-1][j]*j)%mod;
		}
		for(i=1;i<=N;i++){
			for(j=1;j<=N;j++) dp[i][j]+=dp[i][j-1];
		}
		while(T--) fin>>x>>y,fout<<dp[x][y]%mod<<'\n';
	}
}
namespace Solve5{
	const int N=1000000;ll frc[N+5],Inv[N+5],Ans;int x,y;I void Make(){
		RI i;for(frc[0]=i=1;i<=N;i++)frc[i]=frc[i-1]*i%mod;Inv[N]=mpow(frc[N]);for(i=N-1;~i;i--) Inv[i]=Inv[i+1]*(i+1)%mod;
		while(T--){
			fin>>x>>y;for(i=0;i<=y;i++) Ans+=(i&1?mod-frc[y]*Inv[i]%mod*Inv[y-i]%mod*mpow(y-i,x)%mod:frc[y]*Inv[i]%mod*Inv[y-i]%mod*mpow(y-i,x)%mod);fout<<Ans%mod*Inv[y]%mod<<'\n';
		}
	}
}
namespace Solve6{
	const int N=1000000;int x,y;ll Inv[N+5],frc[N+5],Ans;I void Make(){
		RI i;for(frc[0]=i=1;i<=N;i++)frc[i]=frc[i-1]*i%mod;Inv[N]=mpow(frc[N]);for(i=N-1;~i;i--) Inv[i]=Inv[i+1]*(i+1)%mod;
		for(i=1;i<=N;i++) Inv[i]=Inv[i]*frc[i-1]%mod;
		while(T--){
			fin>>x>>y;y--;Ans=1;for(i=x+1;i<=y+x;i++) Ans=Ans*i%mod;for(i=1;i<=y;i++) Ans=Ans*Inv[i]%mod;fout<<Ans<<'\n';
		}
	}
}
namespace Solve7{
	const int N=1000000;ll Inv[N+5],frc[N+5],Ans;int x,y;I void Make(){
		RI i;for(frc[0]=i=1;i<=N;i++)frc[i]=frc[i-1]*i%mod;Inv[N]=mpow(frc[N]);for(i=N-1;~i;i--) Inv[i]=Inv[i+1]*(i+1)%mod;
		while(T--){
			fin>>x>>y;fout<<(x>y?0:frc[y]*Inv[x]%mod*Inv[y-x])%mod<<'\n';
		}
	}
}
namespace Solve8{
    I ll mpow(ll x,int p,int y){ll Ans=1;while(y) y&1&&(Ans=Ans*x%p),y>>=1,x=x*x%p;return Ans;}
	const int N=40000,p1=3,p2=10007,p3=35617,Mod=p1*p2*p3;int X[N+5<<2],Y[N+5<<2];ll Inv[N+5],frc[N+5],Ans,A1[N+5<<2],A2[N+5<<2],A3[N+5<<2];
	I ll Lucas(int n,int m,int p){if(!n||!m) return 1;return (n%p<m%p?0:frc[n%p]*Inv[m%p]%p*Inv[n%p-m%p]%p)*Lucas(n/p,m/p,p)%p;}
	I void Make(){
		RI i;for(i=1;i<=T;i++)fin>>X[i]>>Y[i],X[i]--,Y[i]--;
		for(frc[0]=Inv[0]=i=1;i<p1;i++) frc[i]=frc[i-1]*i%p1,Inv[i]=mpow(frc[i],p1,p1-2);for(i=1;i<=T;i++) A1[i]=Lucas(X[i],Y[i],p1);
		for(frc[0]=Inv[0]=i=1;i<p2;i++) frc[i]=frc[i-1]*i%p2,Inv[i]=mpow(frc[i],p2,p2-2);for(i=1;i<=T;i++) A2[i]=Lucas(X[i],Y[i],p2);
		for(frc[0]=Inv[0]=i=1;i<p3;i++) frc[i]=frc[i-1]*i%p3,Inv[i]=mpow(frc[i],p3,p3-2);for(i=1;i<=T;i++) A3[i]=Lucas(X[i],Y[i],p3);
		for(i=1;i<=T;i++) fout<<(Y[i]>X[i]?0:(A1[i]*p2*p3%Mod*mpow(p2*p3,p1,p1-2)+A2[i]*p1*p3%Mod*mpow(p1*p3,p2,p2-2)+A3[i]*p1*p2%Mod*mpow(p1*p2,p3,p3-2))%Mod)<<'\n';
	}
}
namespace Solve9{
	const int N=5000;ll dp[N+5][N+5];int x,y;I void Make(){
		RI i,j;for(i=0;i<=N;i++) dp[0][i]=1;for(i=1;i<=N;i++){
			for(j=0;j<=N;j++) dp[i][j]=dp[i][j-1],i>=j&&(dp[i][j]=(dp[i][j]+dp[i-j][j])%mod);
		}while(T--) fin>>x>>y,fout<<dp[x][y]<<'\n';
	}
}
namespace Solve10{
	const int N=5000;ll dp[N+5][N+5];int x,y;I void Make(){
		RI i,j;for(i=0;i<=N;i++) dp[0][i]=1;for(i=1;i<=N;i++){
			for(j=0;j<=N;j++) dp[i][j]=dp[i][j-1],i>=j&&(dp[i][j]=(dp[i][j]+dp[i-j][j])%mod);
		}while(T--) fin>>x>>y,fout<<(x>=y?dp[x-y][y]:0)<<'\n';
	}
}
int main(){
	freopen("1.in","r",stdin);freopen("1.out","w",stdout);
    fin>>T>>op;
    if(op==1) Solve1::Make();
	if(op==2) Solve2::Make();
    if(op==3) Solve3::Make();
    if(op==4) Solve4::Make();
    if(op==5) Solve5::Make();
	if(op==6) Solve6::Make();
    if(op==7) Solve7::Make();
    if(op==8) Solve8::Make();
    if(op==9) Solve9::Make();
    if(op==10) Solve10::Make();
    // 不建議用 scanf 和 printf,會多佔用 0.2 s 的時間、
    return 0;
}