Special test mathematics 3

A. Solving equation

It is easy to do without considering the two restrictions. Use the board inserting method to divide \ (m \) balls into \ (n \) piles

It's \ (\ binom{m-1}{n-1} \)

The second limit is greater than or equal to, so you can allocate \ (a_i-1 \) to these numbers first

The first restriction is not easy to do directly, so consider inclusion and exclusion, and subtract the number of illegal schemes from the total number of schemes

The illegal restriction is \ (x > a_i \) in the same form as the second restriction

Then the rest is directly exclusive

Code
#include<bits/stdc++.h>
#define int long long
#define rint signed
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
int T,p,n,n1,n2,m,U,ans;
int a[20];
inline void sc(){
	n=read(),n1=read(),n2=read(),m=read();
	for(int i=1;i<=n1+n2;i++) a[i]=read();
}
namespace P1{
	#define mod 10007
	int fac[10010],inv[10010];
	inline int qpow(int x,int k){
		int res=1,base=x;
		while(k){if(k&1) res=res*base%mod;base=base*base%mod;k>>=1;}
		return res;
	}
	inline void pre(){fac[0]=inv[0]=1;for(int i=1;i<=10006;i++) fac[i]=fac[i-1]*i%mod,inv[i]=inv[i-1]*qpow(i,mod-2)%mod;}
	inline int C(int n,int m){return fac[n]*inv[m]%mod*inv[n-m]%mod;}
	inline int Lucas(int n,int m){
		if(n<0||m>n) return 0;if(!m) return 1;if(n<mod&&m<mod) return C(n,m);
		return C(n%mod,m%mod)*Lucas(n/mod,m/mod)%mod;
	}
	inline void solve(){
		sc();ans=0;for(int i=n1+1;i<=n1+n2;i++) m-=a[i]-1;U=(1<<n1)-1;
		if(m-1<n-1) return puts("0"),void();
		for(int sta=0,sum,r;sta<=U;sta++){
			sum=m;r=(__builtin_popcount(sta)&1)?-1:1;
			for(int i=1;i<=n1;i++) if(sta&(1<<(i-1))) sum-=a[i];
			ans=(ans+r*Lucas(sum-1,n-1)+mod)%mod;
		}
		printf("%lld\n",ans);
	}
	#undef mod
}
namespace P2{
	#define mod 262203414
	int A[10],pA[10],B[10];//2*3*11*397*10007
	int f[10010][10];
	inline int qpow(int x,int k,int p){
		int res=1,base=x;
		while(k){if(k&1) res=res*base%p;base=base*base%p;k>>=1;}
		return res;
	}
	inline void pre(){
		A[1]=2,pA[1]=2;
		A[2]=3,pA[2]=3;
		A[3]=11,pA[3]=11;
		A[4]=397,pA[4]=397;
		A[5]=10007,pA[5]=10007;
		for(int i=1,r;i<=5;i++){
			f[0][i]=r=1;
			for(int j=1,x;j<=A[i];j++){
				x=j;while(x%pA[i]==0) x/=pA[i];
				r=r*x%A[i];f[j][i]=r;
			}
		}
	}
	void exgcd(int a,int b,int &x,int &y){
		if(!b) return x=1,y=0,void();
		exgcd(b,a%b,x,y);int tmp=x;x=y;y=tmp-a/b*y;
	}
	inline int INV(int a, int p){int x,y;exgcd(a,p,x,y);return (x+p)%p;}
	inline int F(int n,int x){
		if(n<=A[x]) return f[n][x];
		int rou=1,rem=1,P=pA[x],PK=A[x];
		for(int i=1;i<=PK;i++) if(i%P) rou=rou*i%PK;
		rou=qpow(rou,n/PK,PK);
		for(int i=PK*(n/PK);i<=n;i++) if(i%P) rem=rem*(i%PK)%PK;
		return (F(n/P,x)*rou%PK*rem%PK);
	}
	inline int G(int n,int P){if(n<P) return 0;return G(n/P,P)+(n/P);}
	inline int C_PK(int n,int m,int x){
		int P=pA[x],PK=A[x];
		int fz=F(n,x),fm1=INV(F(m,x),PK),fm2=INV(F(n-m,x),PK);
		int mi=qpow(P,G(n,P)-G(m,P)-G(n-m,P),PK);
		return fz*fm1%PK*fm2%PK*mi%PK;
	}
	inline int exLucas(int n,int m){
		if(n<0||m>n) return 0;if(!m) return 1;
		for(int i=1;i<=5;i++) B[i]=C_PK(n,m,i);
		int res=0;
		for(int i=1,M,T;i<=5;i++){
			M=mod/A[i];T=INV(M,A[i]);
			res=(res+B[i]*M%mod*T%mod)%mod;
		}
		return res;
	}
	inline void solve(){
		sc();ans=0;for(int i=n1+1;i<=n1+n2;i++) m-=a[i]-1;U=(1<<n1)-1;
		if(m-1<n-1) return puts("0"),void();
		for(int sta=0,sum,r;sta<=U;sta++){
			sum=m;r=(__builtin_popcount(sta)&1)?-1:1;
			for(int i=1;i<=n1;i++) if(sta&(1<<(i-1))) sum-=a[i];
			ans=(ans+r*exLucas(sum-1,n-1)+mod)%mod;
		}
		printf("%lld\n",ans);
	}
	#undef mod
}
namespace P3{
	#define mod 437367875
	int A[10],pA[10],B[10];//5*5*5*7*7*7*101*101
	int f[10300][5];
	inline int qpow(int x,int k,int p){
		int res=1,base=x;
		while(k){if(k&1) res=res*base%p;base=base*base%p;k>>=1;}
		return res;
	}
	inline void pre(){
		A[1]=125,pA[1]=5;
		A[2]=343,pA[2]=7;
		A[3]=10201,pA[3]=101;
		for(int i=1,r;i<=3;i++){
			f[0][i]=r=1;
			for(int j=1,x;j<=A[i];j++){
				x=j;while(x%pA[i]==0) x/=pA[i];
				r=r*x%A[i];f[j][i]=r;
			}
		}
	}
	void exgcd(int a, int b, int &x, int &y){
		if(!b) return x=1,y=0,void();
		exgcd(b,a%b,x,y);int tmp=x;x=y;y=tmp-a/b*y;
	}
	inline int INV(int a, int p){int x,y;exgcd(a,p,x,y);return (x+p)%p;}
	inline int F(int n,int x){
		if(n<=A[x]) return f[n][x];
		int rou=1,rem=1,P=pA[x],PK=A[x];
		for(int i=1;i<=PK;i++) if(i%P) rou=rou*i%PK;
		rou=qpow(rou,n/PK,PK);
		for(int i=PK*(n/PK);i<=n;i++) if(i%P) rem=rem*(i%PK)%PK;
		return (F(n/P,x)*rou%PK*rem%PK);
	}
	inline int G(int n,int P){if(n<P) return 0;return G(n/P,P)+(n/P);}
	inline int C_PK(int n,int m,int x){
		int P=pA[x],PK=A[x];
		int fz=F(n,x),fm1=INV(F(m,x),PK),fm2=INV(F(n-m,x),PK);
		int mi=qpow(P,G(n,P)-G(m,P)-G(n-m,P),PK);
		return fz*fm1%PK*fm2%PK*mi%PK;
	}
	inline int exLucas(int n,int m){
		if(n<0||m>n) return 0;if(!m) return 1;
		for(int i=1;i<=3;i++) B[i]=C_PK(n,m,i);
		int res=0;
		for(int i=1,M,T;i<=3;i++){
			M=mod/A[i];T=INV(M,A[i]);
			res=(res+B[i]*M%mod*T%mod)%mod;
		}
		return res;
	}
	inline void solve(){
		sc();ans=0;for(int i=n1+1;i<=n1+n2;i++) m-=a[i]-1;U=(1<<n1)-1;
		if(m-1<n-1) return puts("0"),void();
		for(int sta=0,sum,r;sta<=U;sta++){
			sum=m;r=(__builtin_popcount(sta)&1)?-1:1;
			for(int i=1;i<=n1;i++) if(sta&(1<<(i-1))) sum-=a[i];
			ans=(ans+r*exLucas(sum-1,n-1)+mod)%mod;
		}
		printf("%lld\n",ans);
	}
	#undef mod
}
signed main(){
#ifdef LOCAL
	freopen("in","r",stdin);
	freopen("out","w",stdout);
#endif
	T=read(),p=read();
	if(p==10007){P1::pre();while(T--) P1::solve();}
	if(p==262203414){P2::pre();while(T--) P2::solve();}
	if(p==437367875){P3::pre();while(T--) P3::solve();}
	return 0;
}

B. Cosmic sequence

Let's talk about violence first. The formula given in the question is a naked XOR convolution, so go directly to the \ (fwt \) violence volume

Convolution has a binding law, so the fast power of matrix (?) can be applied. This is not likely to be proved, but at least the convolution of addition and subtraction and bit operation have this property

It is found that adding at the same position in the point-to-point representation does not affect the values at other positions (it will not prove that convolution seems to have this property? I don't understand

With the above two, we can change the convolution of violence \ (fwt \)

Set \ (a_i \) as the subscript value of \ (I \) under the point value representation, and then add all values to the \ (b \) array

\(b_i=\sum\limits_{i=0}^pa_i^{2^j}\)

Finally, find \ (b \) from \ (IDFT \) again

Then the problem becomes how to find the value of each point. You can use the multiplication method or find the cyclic node

I use multiplication to achieve

Set \ (f {x, K} = \ sum \ limits {I = 0} ^ {2 ^ k-1} x ^ {2 ^ I} \)

Then there is \ (f {x, K} = f {x, k-1} + F {x ^ {2 ^ {k-1}}, k-1} \)

Just change the above \ (x \) into the item \ (2^k \) of the above formula, and then spell it together

Then calculate the final coefficient for each value. The calculation method is the same as the multiplication method. You can draw a diagram and see the code implementation

Code
#include<bits/stdc++.h>
#define int long long
#define rint signed
#define mod 10007
#define i2 5004
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
int n,p,J,len,ans;
int a[262200];
int f[10010][40],F[10010],k2[40];
inline void md(int &x){x=(x>=mod)?x-mod:x;}
inline int qpow(int x,int k,int p){
	int res=1,base=x;
	while(k){if(k&1) res=res*base%p;base=base*base%p;k>>=1;}
	return res;
}
inline void fwt(int tx){
	for(int d=1;d<len;d<<=1) for(int i=0;i<len;i+=(d<<1)) for(int j=0;j<d;j++){
		int x=a[i+j],y=a[i+j+d];
		md(a[i+j]=(x+y));md(a[i+j+d]=(x-y+mod));
		if(tx==-1) a[i+j]=a[i+j]*i2%mod,a[i+j+d]=a[i+j+d]*i2%mod;
	}
}
inline void pre(){
	k2[0]=1;for(int i=1;i<=35;i++) k2[i]=k2[i-1]*2;
	for(int i=0;i<mod;i++) f[i][0]=i;
	for(int j=1;j<=35;j++) for(int i=0,to;i<mod;i++){
		to=qpow(i,qpow(2,k2[j-1],mod-1),mod);
		f[i][j]=(f[i][j-1]+f[to][j-1])%mod;
	}
	for(int i=0,x,k,to;i<mod;i++){
		x=i,k=p+1;
		for(int j=35;~j;j--) if((1ll<<j)<=k){
			k-=(1ll<<j);
			F[i]=(F[i]+f[x][j])%mod;
			x=qpow(x,qpow(2,k2[j],mod-1),mod);
		}
	}
}
signed main(){
#ifdef LOCAL
	freopen("in","r",stdin);
	freopen("out","w",stdout);
#endif
	n=read(),p=read(),J=read();len=1<<n;pre();
	for(int i=0;i<len;i++) a[i]=read();
	fwt(1);for(int i=0;i<len;i++) a[i]=F[a[i]];fwt(-1);
	printf("%lld\n",a[J]);
	return 0;
}

C. exp

It is found that for an interval, if a \ (. \) in the middle does not become \ (x \), the two intervals divided by this point do not affect each other

Consider \ (dp \) based on this property

Let \ (f(l,r) \) represent the expectation that the interval \ ([l,r-1] \) has become \ (x \) and \ (r \) is \ (. \)

\(g(l,r) \) has the same definition, but it is probability

\(p(l,r,k) \) indicates the probability that the interval \ ([l,k-1] \) and \ ([k+1,r-1] \) have become the \ (K \) position of \ (x \) and finally become \ (x \)

Then there are \ (g(l,r)=\sum\limits_{k=l}^{r-1}p(l,r,k),f(l,r)=\frac{1}{g(l,r)}\sum\limits_{k=l}^{r-1}p_{l,r,k}*(f(l,k)+f(k+1,r)+\frac{k-l}{2})\)

\(\ frac{k-l}{2} \) is the number of steps expected to be added

Simply deduce that the total number of steps increased is \ (0,1,...,k-l \) and the sum of the arithmetic sequence is \ (\ frac{(k-l)*(k-l+1)}{2} \)

Then the probability of each case is \ (\ frac{1}{(k-l+1)} \), so the last is \ (\ frac{k-l}{2} \)

The steps taken form a ring, so consider breaking the ring as a chain, enumerate where the last eliminated position is, and add the last contribution \ (\ frac{n-1}{2} \)

The answer is \ (\ frac {n-1} {2} + \ sum \ limits {I = 1} ^ ng (I, I + n-1) * f (I, I + n-1) \)

Then consider how to find \ (p(l,r,k) \)

Set \ (lc,rc \) around \ (k \) \ (. \)

There are \ ((r-l+1)^{lc+rc+1} \) cases in total

Then there are \ (\ binom{lc+rc}{lc} \) schemes to allocate and eliminate the order of \ (. \) on the left and right sides

The number of schemes to eliminate the left and right \ (. \) is \ ((k-l+1)^{lc}*g(l,k)*(r-k)^{rc}*g(k+1,r) \)

The number of legal schemes on the left of extinction is multiplied by the probability. The same is true on the right

The last time \ (k \) must be eliminated, so there is \ (k-l+1 \)

So \ (p(l,r,k)=\binom{lc+rc}{lc}*(\frac{k-l+1}{r-l+1})^{lc}*g(l,k)*(\frac{r-k}{r-l+1})^{rc}*g(k+1,r)*\frac{k-l+1}{r-l+1} \)

Finally, pay attention to judge that it is all \ (x \)

Code
#include<bits/stdc++.h>
#define int long long
#define rint signed
#define eps 1e-8
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
int T,n;
int cnt[410];
double C[410][410];
double f[410][410],g[410][410],ans;
char st[410];
inline void pre(){for(int i=0;i<=400;i++) for(int j=C[i][0]=1;j<=i;j++) C[i][j]=C[i-1][j-1]+C[i-1][j];}
inline double qpow(double x,int k){
	double res=1,base=x;
	while(k){if(k&1) res=res*base;base=base*base;k>>=1;}
	return res;
}
inline double p(int l,int r,int k){
	int lc=cnt[k-1]-cnt[l-1],rc=cnt[r-1]-cnt[k];
	return C[lc+rc][lc]*qpow(1.0*(k-l+1)/(r-l+1),lc)*g[l][k]*qpow(1.0*(r-k)/(r-l+1),rc)*g[k+1][r]*1.0*(k-l+1)/(r-l+1);
}
inline void solve(){
	scanf("%s",st+1);n=strlen(st+1);for(int i=1;i<=n;i++) st[i+n]=st[i];n<<=1;
	memset(f,0,sizeof(f));memset(g,0,sizeof(g));memset(cnt,0,sizeof(cnt));ans=0;
	for(int i=1;i<=n;i++) cnt[i]=cnt[i-1]+(st[i]=='.');
	for(int len=1;len<=(n>>1);len++) for(int l=1,r,fg;l+len-1<=n;l++) {
		r=l+len-1;
		fg=1;for(int i=l;i<r;i++) if(st[i]=='.') fg=0;
		if(fg&&st[r]=='.'){
			g[l][r]=1,f[l][r]=0;
		}else{
			for(int k=l;k<r;k++){
				double res=p(l,r,k);
				g[l][r]+=res;
				f[l][r]+=res*(f[l][k]+f[k+1][r]+(k-l)/2.0);
			}
			if(g[l][r]>eps) f[l][r]/=g[l][r];
		}
	}
	n>>=1;for(int i=1;i<=n;i++) ans+=(g[i][i+n-1]*f[i][i+n-1]);if(cnt[n]) ans=ans+(n-1)/2.0;
	printf("%.10lf\n",ans);
}
signed main(){
#ifdef LOCAL
	freopen("in","r",stdin);
	freopen("out","w",stdout);
#endif
	pre();T=read();while(T--) solve();
	return 0;
}

Keywords: number theory dp FWT

Added by froggie81 on Fri, 07 Jan 2022 13:28:39 +0200