A-平面

题目链接:https://www.nowcoder.com/acm/contest/180#question
假设有n条直线,增加第 n 条直线,最多与前面 n 1 条直线相交,因此 n 条直线最多相交出 1 + 2 + 3 + . . . + ( n 1 ) = n ( n 1 ) 2 个点,记点数为:

V e r t e x = n ( n 1 ) 2

n 条直线 V e r t e x 个交点能够分成多少条线段呢? n + 2 V e r t e x
记线段的个数为:
E d g e = n + 2 V e r t e x

然后就阔以用 欧拉平面公式 计算区域数了:
V e r t e x + F a c e E d g e = 1

D-XOR序列

原来这个就是线性基的经典操作题,还是第一次听说这个
大概的过程就跟求线性代数里的 行最简形 差不多
用样例来讲一讲大概的过程:
有5个数{1,2,3,4,5},化成二进制最大的数也只有3位,因此是构造一个 3 × 3 的矩阵
最开始是:

[ 0 0 0 0 0 0 0 0 0 ]

然后加入 001 2 ,因为最高位在第 0 位,所以加在最后一行

[ 0 0 0 0 0 0 0 0 1 ]

然后加入 010 2 ,最高位在第 1 位,所以加在第二行
[ 0 0 0 0 1 0 0 0 1 ]

然后加入 011 2 ,本来应该加在第二行的,但是第二行已经不是0了,所以用第二行把 011 2 中的第1位消掉,变成了 001 2 ,然后第3行也不是0,又用第三行把第0位消掉,就变成了 000 2 ,所以相当于 011 2 这个数对矩阵没有做贡献,为什么喃?因为 011 2 阔以用 010 2 001 2 线性组合表示出来。

再加入 100 2 矩阵变成:

[ 1 0 0 0 1 0 0 0 1 ]

101 2 也加不进去了

然后矩阵就构造好了,怎么用喃?
假设要看能不能异或出来一个数,就从最高位开始枚举,如果那一位有1,就对应的行去异或,最后如果等于0,那就说明阔以异或出来。

#include"bits/stdc++.h"
using namespace std;
const int maxn=1e6+5;
const int MOD=1e9+7;
typedef long long LL;
int p[35];
int main()
{
    int N,Q;
    cin>>N;
    for(int i=1;i<=N;i++)
    {
        int t;
        cin>>t;
        for(int j=31;j>=0;j--)//从高位开始枚举这个数的每一位 
        {
            if(t&(1<<j))//假如第j位有1 
            {
                if(p[j]==0)//如果这一行还没有动过,就直接赋值 
                {
                    p[j]=t;
                    break;
                }
                else t^=p[j];//用第j行来消去开头的t的第j位的1 
            }
        }
    }
    cin>>Q;
    while(Q--)
    {
        int x,y;
        cin>>x>>y;
        x^=y;
        for(int j=31;j>=0;j--)if(x&(1<<j))x^=p[j];
        if(x==0)cout<<"YES\n";
        else cout<<"NO\n";
    }

}

B-烟花

就跟背包问题差不多,每次考虑这个物品取或者不取:

二维的:

d p [ i ] [ k ] 表示前 i 个物品中取 k 个的概率

#include"bits/stdc++.h"
#define out(x) cout<<#x<<"="<<x
#define C(n,m) (m>n?0:(long long)fac[(n)]*invf[(m)]%MOD*invf[(n)-(m)]%MOD)
using namespace std;
typedef long long LL;
const int maxn=1e5+5;
const int MOD=1e9+7;
double dp[maxn][205];
double p[maxn];
double sum;
int main()
{
    cout.setf(ios::fixed);
    int N,K;
    while(cin>>N>>K)
    {
        memset(dp,0,sizeof dp);
        sum=0;
        cin>>p[1];
        sum+=p[1];
        dp[1][1]=p[1],dp[1][0]=1-p[1];
        for(int i=2;i<=N;i++)
        {
            cin>>p[i];
            sum+=p[i];
            for(int k=1;k<=i&&k<=K;k++)
            {
                dp[i][k]=p[i]*dp[i-1][k-1]+(1.0-p[i])*dp[i-1][k];
            }
        }
        cout<<setprecision(4)<<sum<<endl<<dp[N][K]<<endl;
    }
}

一维的:


#include"bits/stdc++.h"
#define out(x) cout<<#x<<"="<<x
#define C(n,m) (m>n?0:(long long)fac[(n)]*invf[(m)]%MOD*invf[(n)-(m)]%MOD)
using namespace std;
typedef long long LL;
const int maxn=1e5+5;
const int MOD=1e9+7;
double dp[205];
double sum,p;
int main()
{
    cout.setf(ios::fixed);
    int N,K;
    while(cin>>N>>K)
    {
        memset(dp,0,sizeof dp);
        sum=0;
        dp[0]=1;
        for(int i=1; i<=N; i++)
        {
            cin>>p;
            sum+=p;
            for(int k=K; k>=1; k--)
            {
                dp[k]=1.0*dp[k-1]*p+1.0*dp[k]*(1-p);
            }
            dp[0]=dp[0]*(1-p);//dp[0]代表的是前i个的物品取0个的概率,所以每次是要变的 
        }
        cout<<setprecision(4)<<sum<<endl<<dp[K]<<endl;
    }
}