P5130 纯粹的弹幕地狱

因为每回合击中的概率是固定的,所以只需要算一次。

概率为:可以击中的情况/总情况。

每个点有 \((n+1)^2\) 个位置,所以总情况为\((n+1)^4\)

可以击中的情况和仪仗队差不多,画个图就知道答案为:

\[4(n-1)n+4\sum_{i=1}^{n-1}\sum_{j=1}^{n-1} [(i,j)=1](n-i)(n-j) \]

\[4(n-1)n+4\sum_{i=1}^{n-1}\sum_{j=1}^{n-1} [(i,j)=1](n^2-(i+j)n+ij) \]

\[4(n-1)n+4\sum_{i=1}^{n-1}\sum_{j=1}^{n-1} \sum_{d|(i,j)} \mu(d)(n^2-(i+j)n+ij) \]

\[4(n-1)n+4\sum_{d=1}^{n-1}\mu(d)\sum_{i=1}^{\lfloor \frac{n-1} {d} \rfloor}\sum_{j=1}^{\lfloor \frac{n-1}{d} \rfloor} (n^2-(i+j)dn+ijd^2) \]

\(T=\lfloor \frac{n-1}{d} \rfloor\) ,则有:

\[4\sum_{d=1}^{n-1}\mu(d)(T ^2n^2-ndT^2(T+1)+\frac{d^2T^2(T+1)^2}{4}) \]

\[4(n-1)n+\sum_{d=1}^{n-1}\mu(d)(4T ^2n^2-4ndT^2(T+1)+d^2T^2(T+1)^2) \]

后面的可以整除分块,预处理 \(\mu,\mu\times i,\mu \times i^2\) 的前缀和后我们便可以在 \(\Theta(\sqrt n)\) 的复杂度解决单次询问。

知道概率 \(p\) 后期望总伤害便为:

\[(\frac{k(k+1)(2k+1)}{6}a+\frac{k(k+1)}{2}b+kc)p \]

所以这道题可以多组输入的

#include <cstdio>

const int MAXN = 1e7 , Mod = 19260817;
const int Inv2 = 9630409 , Inv6 = 16050681;

int a , b , c , n , k;
int p , atk;

int prn , prime[ MAXN + 5 ] , mu[ MAXN + 5 ];
int f1[ MAXN + 5 ] , f2[ MAXN + 5 ] , f3[ MAXN + 5 ];
bool vis[ MAXN + 5 ];
void sieve( ) {
	mu[ 1 ] = 1;
	for( int i = 2 ; i <= n ; i ++ ) {
		if( !vis[ i ] ) { prime[ ++ prn ] = i; mu[ i ] = -1; }
		for( int j = 1 ; j <= prn && 1ll * i * prime[ j ] <= MAXN ; j ++ ) {
			vis[ i * prime[ j ] ] = 1;
			if( i % prime[ j ] == 0 ) break;
			mu[ i * prime[ j ] ] = -mu[ i ];
		}
	}
	for( int i = 1 ; i <= n ; i ++ ) {
		f1[ i ] = ( f1[ i - 1 ] + mu[ i ] + Mod ) % Mod;
		f2[ i ] = ( f2[ i - 1 ] + mu[ i ] * i + Mod ) % Mod;
		f3[ i ] = ( f3[ i - 1 ] + 1ll * mu[ i ] * i * i % Mod + Mod ) % Mod;
	}
}

int Quick_pow( int x , int po ) {
	int Ans = 1;
	for( ; po ; po >>= 1 , x = 1ll * x * x % Mod )
		if( po & 1 ) Ans = 1ll * Ans * x % Mod;
	return Ans;
}
int Inverse( int x ) {
	return Quick_pow( x , Mod - 2 );
}

int Calc1( int x ) { return 1ll * x * ( x + 1 ) % Mod * Inv2 % Mod; }
int Calc2( int x ) { return 1ll * x * ( x + 1 ) % Mod * ( 2 * x % Mod + 1 ) % Mod * Inv6 % Mod; }

int main( ) {
	scanf("%d %d %d %d %d",&n,&a,&b,&c,&k); n ++; sieve( );
	
	atk = ( 1ll * Calc2( k ) * a % Mod + 1ll * Calc1( k ) * b % Mod + 1ll * k * c % Mod ) % Mod;
	
	p = 4ll * ( n - 1 ) * n % Mod;
	for( int l = 1 , r , T ; l <= n - 1 ; l = r + 1 ) {
		r = ( n - 1 ) / ( ( n - 1 ) / l ); T = ( n - 1 ) / l;
		p = ( p + 4ll * ( f1[ r ] - f1[ l - 1 ] + Mod ) % Mod * T % Mod * T % Mod * n % Mod * n % Mod - 4ll * ( f2[ r ] - f2[ l - 1 ] + Mod ) % Mod * n % Mod * T % Mod * T % Mod * ( T + 1 ) % Mod + 1ll * ( f3[ r ] - f3[ l - 1 ] + Mod ) % Mod * T % Mod * T % Mod * ( T + 1 ) % Mod * ( T + 1 ) % Mod + Mod ) % Mod;
	}
	
	int Invn = Inverse( n );
	p = 1ll * p * Invn % Mod * Invn % Mod * Invn % Mod * Invn % Mod;
	printf("%d\n", 1ll * atk * p % Mod );			
	return 0;
}
posted @ 2021-04-08 20:46  chihik  阅读(85)  评论(0编辑  收藏  举报