B組T4 JZOJ 1353 有趣的數列
題目
我們稱一個長度爲的數列是有趣的,當且僅當該數列滿足以下三個條件:
(1)它是從到共個整數的一個排列;
(2)所有的奇數項滿足,所有的偶數項滿足;
(3)任意相鄰的兩項滿足奇數項小於偶數項,即:。
現在的任務是:對於給定的,請求出有多少個不同的長度爲的有趣的數列。因爲最後的答案可能很大,所以只要求輸出答案的值。
分析
這道題目也就是在求,由於可能不存在逆元,所以分解質因數求答案
代碼
#include <cstdio>
#define rr register
using namespace std;
const int N=2e6+5;
int c[N],v[N],prime[N],lim,n,mod,ans=1,cnt;
inline void dfs(int x,int z){
if (x==1) return;
c[v[x]]+=z,dfs(x/v[x],z);
}
inline signed ksm(int x,int y){
rr int ans=1;
for (;y;y>>=1,x=1ll*x*x%mod)
if (y&1) ans=1ll*ans*x%mod;
return ans;
}
signed main(){
scanf("%d%d",&n,&mod),lim=2*n;
for (rr int i=2;i<=lim;++i){
if (!v[i]) v[i]=prime[++cnt]=i;
for (rr int j=1;j<=cnt&&prime[j]*i<=lim;++j){
v[i*prime[j]]=prime[j];
if (i%prime[j]==0) break;
}
}
for (rr int i=n+2;i<=2*n;++i) dfs(i,1);
for (rr int i=2;i<=n;++i) dfs(i,-1);
for (rr int i=2;i<=2*n;++i) ans=1ll*ans*ksm(i,c[i])%mod;
return !printf("%d",ans);
}
A組T1 JZOJ 6403 A
題目
分析
考慮容斥,即用總方案減去不合法的方案,若向軸正方向走步,向軸正方向走步,向軸正方向走步,記作,那麼方案數也就是
設表示經過第個不可經過的點而沒有經過前個不可經過的點的方案數
那麼
特殊地,把終點也當做不可經過的點已統計最終答案,因爲座標必須遞增,所以先給不可經過的點升序排序,若這個不可經過的點無法到達下一個點,則不需轉移
代碼
#include <cstdio>
#include <cctype>
#include <algorithm>
#define rr register
using namespace std;
const int mod=1e9+7,N=3e5+5,M=5e4+5;
struct rec{int x,y,z;}a[M];
int fac[N],inv[N],n,m,lim,dp[M];
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
bool cmp(const rec &a,const rec &b){
return a.x<b.x||(a.x==b.x&&(a.y<b.y||(a.y==b.y&&a.z<b.z)));
}
inline signed mo(int x,int y){return x+y>=mod?x+y-mod:x+y;}
inline signed doit(int x,int y,int z){return 1ll*fac[x+y+z]*inv[x]%mod*inv[y]%mod*inv[z]%mod;}
signed main(){
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
n=iut(),m=iut(),fac[0]=fac[1]=inv[0]=inv[1]=1,lim=3*n;
for (rr int i=1;i<=m;++i) a[i].x=iut(),a[i].y=iut(),a[i].z=iut();
for (rr int i=2;i<=lim;++i) inv[i]=1ll*inv[mod%i]*(mod-mod/i)%mod; a[++m]=(rec){n,n,n};
for (rr int i=2;i<=lim;++i) fac[i]=1ll*fac[i-1]*i%mod,inv[i]=1ll*inv[i-1]*inv[i]%mod;
sort(a+1,a+1+m,cmp);
for (rr int i=1;i<=m;++i){
dp[i]=doit(a[i].x,a[i].y,a[i].z);
for (rr int j=1;j<i;++j){
if (a[j].x>a[i].x||a[j].y>a[i].y||a[j].z>a[i].z) continue;
dp[i]=mo(dp[i],mod-1ll*dp[j]*doit(a[i].x-a[j].x,a[i].y-a[j].y,a[i].z-a[j].z)%mod);
}
}
return !printf("%d",dp[m]);
}
A組T3 JZOJ 6405 C
題目
分析
根據一系列的找規律可以發現其實它在求
然後後面這一坨等於
所以求解
代碼
#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
const int mod=1e9+7,N=1e6+5;
int n,ans,fac[N<<1],jc[N],prime[N],cnt,m; bool v[N];
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
inline signed mo(int x,int y){return x+y>=mod?x+y-mod:x+y;}
inline signed ksm(int x,int y){
rr int ans=1;
for (;y;y>>=1,x=1ll*x*x%mod)
if (y&1) ans=1ll*ans*x%mod;
return ans;
}
inline void pro(int lim){
jc[0]=jc[1]=fac[0]=fac[1]=1;
for (rr int i=2;i<=lim*2;++i) fac[i]=1ll*fac[i-1]*i%mod;
for (rr int i=2;i<=lim;++i){
if (!v[i]) prime[++cnt]=i,jc[i]=ksm(i,m);
for (rr int j=1;j<=cnt&&prime[j]*i<=lim;++j){
v[i*prime[j]]=1,jc[i*prime[j]]=1ll*jc[i]*jc[prime[j]]%mod;
if (i%prime[j]==0) break;
}
}
}
signed main(){
freopen("c.in","r",stdin);
freopen("c.out","w",stdout);
n=iut(),m=(iut()<<1)%(mod-1),pro(n);
rr int inv=ksm(fac[n],mod-3);
for (rr int i=n;i;--i){
ans=mo(ans,1ll*jc[i]*mo(1ll*fac[i<<1]*inv%mod,mod-1)%mod);
inv=1ll*inv*i%mod*i%mod;
}
return !printf("%d",ans);
}