牛客网暑期多校训练营 (第九场)

A.

链接:https://www.nowcoder.com/acm/contest/147/A
来源:牛客网

题目描述

Niuniu has recently learned how to use Gaussian elimination to solve systems of linear equations.
Given n and a[i], where n is a power of 2, let's consider an n x n matrix A.

The index of A[i][j] and a[i] are numbered from 0.
The element A[i][j] satisfies A[i][j] = a[i xor j],
https://en.wikipedia.org/wiki/Bitwise_operation#XOR

Let p = 1000000007.
Consider the equation 
A x = b (mod p)
where A is an n x n matrix, and x and b are both n x 1 row vector.

Given n, a[i], b[i], you need to solve the x.
For example, when n = 4, the equations look like
A[0][0]*x[0] + A[0][1]*x[1] + A[0][2]*x[2] + A[0][3]*x[3] = b[0] (mod p)
A[1][0]*x[0] + A[1][1]*x[1] + A[1][2]*x[2] + A[1][3]*x[3] = b[1] (mod p)
A[2][0]*x[0] + A[2][1]*x[1] + A[2][2]*x[2] + A[2][3]*x[3] = b[2] (mod p)
A[3][0]*x[0] + A[3][1]*x[1] + A[3][2]*x[2] + A[3][3]*x[3] = b[3] (mod p)
and the matrix A can be decided by the array a.

It is guaranteed that there is a unique solution x for these equations.

输入描述:

The first line contains an integer, which is n.
The second line contains n integers, which are the array a.
The third line contains n integers, which are the array b.

1 <= n <= 262144
p = 1000000007
0 <= a[i] < p
0 <= b[i] < p

输出描述:

The output should contains n lines.
The i-th(index from 0) line should contain x[i].
x[i] is an integer, and should satisfy 0 <= x[i] < p.
示例1

输入

复制
4
1 10 100 1000
1234 2143 3412 4321

输出

复制
4
3
2
1
思路分析 : sigma(a[i^j]*x[j]) (0 <= j < n) = b[i] , 因为 i^j^j = i, 所以此式可以变为
 , 然后不就是一个fwt 就可以了
  
  

代码示例:

 
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const ll maxn = 3e5+5;
const ll mod = 1e9+7;

ll n;
ll a[maxn], b[maxn];
void fwt(ll *a)
{
    for(ll d=1;d<n;d<<=1)
        for(ll m=d<<1,i=0;i<n;i+=m)
            for(ll j=0;j<d;j++)
            {
                ll x=a[i+j],y=a[i+j+d];
                a[i+j]=(x+y)%mod,a[i+j+d]=(x-y+mod)%mod;
                //xor:a[i+j]=x+y,a[i+j+d]=x-y;
                //and:a[i+j]=x+y;
                //or:a[i+j+d]=x+y;
            }
}

ll qw(ll a, ll b){
	ll res = 1;
	while(b){
		if (b&1) res = res*a%mod;
		a = a*a%mod;
		b >>= 1;
	}
	return res;
}

int main () {
	cin >> n;
	
	for(ll i = 0; i < n; i++){
		scanf("%lld", &a[i]);
	}	
	for(ll i = 0; i < n; i++){
		scanf("%lld", &b[i]);
	}
	fwt(a); fwt(b);
	for(ll i = 0; i < n; i++){
		if (a[i] != 0){
			b[i] = b[i]*qw(a[i], mod-2)%mod;
		}
	}
	fwt(b);
	for(ll i = 0; i < n; i++){
		b[i] = b[i]*qw(n, mod-2)%mod;
		printf("%lld\n", b[i]);
	}
	
	return 0;
}

 


E .

链接:https://www.nowcoder.com/acm/contest/147/E
来源:牛客网

题目描述
Niuniu likes to play OSU!
We simplify the game OSU to the following problem.

Given n and m, there are n clicks. Each click may success or fail.
For a continuous success sequence with length X, the player can score X^m.
The probability that the i-th click success is p[i]/100.
We want to know the expectation of score.
As the result might be very large (and not integral), you only need to output the result mod 1000000007.
输入描述:

The first line contains two integers, which are n and m.
The second line contains n integers. The i-th integer is p[i].

1 <= n <= 1000
1 <= m <= 1000
0 <= p[i] <= 100

输出描述:

You should output an integer, which is the answer.

示例1
输入
复制

3 4
50 50 50

输出
复制

750000020

说明

000 0
001 1
010 1
011 16
100 1
101 2
110 16
111 81

The exact answer is (0 + 1 + 1 + 16 + 1 + 2 + 16 + 81) / 8 = 59/4.
As 750000020 * 4 mod 1000000007 = 59
You should output 750000020.

备注:

If you don't know how to output a fraction mod 1000000007,
You may have a look at https://en.wikipedia.org/wiki/Modular_multiplicative_inverse

 

题意 : 有一个长度为 n 的序列,每个位置的可能情况是 0 或 1,并且告诉你每个位置出现 1 的概率是多少, 当一串连续的1在一块时它的得分是 连续 1 的长度的 m 次方,求期望的得分

思路分析 :

弱鸡只会一个 n^2 的解法,即相加所有可能的情况的和

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const ll maxn = 1005;
const ll mod = 1e9+7;
const ll inv = 570000004;

ll p[maxn];
ll n, m;
ll a[maxn][maxn];

void init(){
	for(ll i = 1; i <= n; i++){
		a[i][i] = p[i]*inv%mod;
		for(ll j = i+1; j <= n; j++){
			a[i][j] = a[i][j-1]*p[j]%mod*inv%mod;
		}
	}
}

ll qw(ll a, ll b){
	ll res = 1;
	while(b){
		if (b&1) res = res*a%mod;
		a = a*a%mod;
		b >>= 1;
	}
	return res;
}

int main() {
	
	cin >> n >> m;
	for(ll i = 1; i <= n; i++) {
		scanf("%lld", &p[i]);	
	}	
	init();
	
	ll ans = 0;
	for(ll i = 0; i <= n; i++){
		for(ll j = i+1; j <= n+1; j++){
			ans += (100-p[i])*inv%mod*(100-p[j])%mod*inv%mod*a[i+1][j-1]%mod*qw(j-i-1, m)%mod;
			ans %= mod; 
		}
	}
	printf("%lld\n", ans);
	return 0;
}

 但是讲题人有一个 n*m 的解法,用到了斯特林数,表示想了很久还是不太懂,----

先扔个代码

#include <bits/stdc++.h>
using namespace std;
int n, m, mod = 1000000007;
long long p[1020];
long long a[1020];
long long b[1020];
long long s[1020][1020];
long long f[1020];
int main() {
    scanf("%d%d", &n, &m);
    s[0][0] = 1;
    for (int i = 0; i <= m; i++) {
        for (int j = 1; j <= i; j++) {
            s[i][j] = (s[i - 1][j - 1] + j * s[i - 1][j]) % mod;
        }
    }
    for (int i = f[0] = 1; i <= m; i++) {
        f[i] = f[i - 1] * i % mod;
    }
    for (int i = 1; i <= n; i++) {
        scanf("%lld", &p[i]);
        p[i] = p[i] * 570000004 % mod;
        for (int j = m; j > 0; j--) {
            a[j] += a[j - 1];
            a[j] *= p[i];
            a[j] %= mod;
            b[j] += a[j];
            b[j] %= mod;
        }
        a[0] = p[i];
        b[0] += a[0];
        b[0] %= mod;
    }
    long long z = 0;
    for (int i = 1; i <= m; i++) {
        z = (z + b[i - 1] * f[i] % mod * s[m][i]) % mod;
    }
    printf("%lld\n", z);
    return 0;
}

 

posted @ 2018-08-22 17:48  楼主好菜啊  阅读(312)  评论(0编辑  收藏  举报