2020牛客暑期多校训练营(第六场)

B.Binary Vector

题意:
设A={0,1},每天Roundgod从{A^n}(即维度为n,每一位由01组成的所有向量的集合)中随机选择一个二进制向量。现在他想知道n天中选取n个线性独立向量的概率在mod1e9 + 7 下的值。
在这里插入图片描述
2020牛客暑期多校训练营(第六场)_第1张图片
其实也可以根据题目下面给出的提示去猜出公式,但是这里的数据实在太大,所以我要打表。
已经知道1/2 %mod == 5e8 + 4,
我们推出f(n) = f(n-1)*(2n - 1) / (2n)
根据此公式推出:
分母的公式为2 1 + 22 + 23 + … 2n
整理得: 2n*(n+1)/2

分子为:21-1 * 22-1 * 23-1…2n-1

又由费马小定理: 1/2 %mod == 2(mod-2)
那么同理1/4 == 1/2 * 1/2 ,所以 1/4 %mod == 2(mod-2) * 2(mod-2)
所以我们可以推到1/2n的逆元上,那么就可以省很多时间
加粗的就是重点理解的地方

AC代码

#include 
inline long long read(){char c = getchar();long long x = 0,s = 1;
while(c < '0' || c > '9') {if(c == '-') s = -1;c = getchar();}
while(c >= '0' && c <= '9') {x = x*10 + c -'0';c = getchar();}
return x*s;}
using namespace std;
#define NewNode (TreeNode *)malloc(sizeof(TreeNode))
#define Mem(a,b) memset(a,b,sizeof(a))
#define lowbit(x) (x)&(-x)
const int N = 2e7 + 5;
const long long INFINF = 0x7f7f7f7f7f7f7f;
const int INF = 0x3f3f3f3f;
const double EPS = 1e-7;
const int mod = 1e9 + 7;
const double II = acos(-1);
const double PP = (II*1.0)/(180.00);
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> piil;
ll arr[N];
ll quick_pow(ll a,ll b)
{
    ll ans = 1;
    while(b)
    {
        if(b&1)
            ans = a*ans%mod;
        b>>=1;
        a = a*a%mod;
    }
    return ans;
}
void solve()
{
    arr[1] = 5e8 + 4;//1/2%mod的结果
    ll b = 2,Inv = arr[1];//b代表的是现在的分母增量,Inv是分母逆元的增量
    for(int i = 2;i <= N;i++)
    {
        b = b *2 % mod;
        Inv = Inv * arr[1] % mod;
        arr[i] = arr[i-1]*(b-1+mod)%mod*Inv%mod;
        //(b-1+mod)%mod为分子增量,Inv为分母增量,而arr[i-1]为前一个数的值,
    }
    for(int i = 2;i <= N;i++)
        arr[i] ^= arr[i-1];
}
signed main()
{
    std::ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    //    freopen("input.txt","r",stdin);
    //    freopen("output.txt","w",stdout);
    solve();
    ll t;
    t = read();
    while(t--)
    {
        ll n;
        n = read();
        printf("%lld\n",arr[n]);
    }
}

C.Combination of Physics and Maths
这里有一个数学原理:

a/b <= a + c / b + d <= c/d
所以,我们选的时候,可以是选一列即可,而在面积S相同的情况下,肯定是分子F越大越好,所以直接枚举即可

AC代码

#include 
inline long long read(){char c = getchar();long long x = 0,s = 1;
while(c < '0' || c > '9') {if(c == '-') s = -1;c = getchar();}
while(c >= '0' && c <= '9') {x = x*10 + c -'0';c = getchar();}
return x*s;}
using namespace std;
#define NewNode (TreeNode *)malloc(sizeof(TreeNode))
#define Mem(a,b) memset(a,b,sizeof(a))
#define lowbit(x) (x)&(-x)
const int N = 2e6 + 5;
const long long INFINF = 0x7f7f7f7f7f7f7f;
const int INF = 0x3f3f3f3f;
const double EPS = 1e-7;
const int mod = 998244353;
const double II = acos(-1);
const double PP = (II*1.0)/(180.00);
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> piil;
signed main()
{
    std::ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    //    freopen("input.txt","r",stdin);
    //    freopen("output.txt","w",stdout);
    int t;
    cin >> t;
    while(t--)
    {
        int n,m;
        cin >> n >> m;
        int arr[n+5][m+5];
        double Max = 0.000000;
        for(int i = 1;i <= n;i++)
            for(int j = 1;j <= m;j++)
                cin >> arr[i][j];
        for(int i = 1;i <= m;i++)
        {
            int sum = 0;
            for(int j = 1;j <= n;j++)
            {
                sum += arr[j][i];
                Max = max(Max,(sum*1.00)/(arr[j][i]));
            }
        }
        cout << fixed << setprecision(8) << Max << endl;
    }
}

E.Easy Construction
有求和公式:
n*(n+1)/2
既然是每一个长度都有,我们何不从长度为n入手呢?(长度为n的只有一个)

所以有情况:
1.当n为偶数时,n*(n+1)/2 % n == n/2,所以k一定等于n/2,然后再按一定方法构造即可

2.当n为奇数时,n*(n+1)/2%n == 0,所以k一定等于0

AC代码

#include 
inline long long read(){char c = getchar();long long x = 0,s = 1;
while(c < '0' || c > '9') {if(c == '-') s = -1;c = getchar();}
while(c >= '0' && c <= '9') {x = x*10 + c -'0';c = getchar();}
return x*s;}
using namespace std;
#define NewNode (TreeNode *)malloc(sizeof(TreeNode))
#define Mem(a,b) memset(a,b,sizeof(a))
#define lowbit(x) (x)&(-x)
const int N = 2e6 + 5;
const long long INFINF = 0x7f7f7f7f7f7f7f;
const int INF = 0x3f3f3f3f;
const double EPS = 1e-7;
const int mod = 998244353;
const double II = acos(-1);
const double PP = (II*1.0)/(180.00);
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> piil;
signed main()
{
    std::ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    //    freopen("input.txt","r",stdin);
    //    freopen("output.txt","w",stdout);
    int n,k;
    cin >> n >> k;
    if(n % 2 != 0 && k == 0)
    {
        cout << n << " ";
        for(int i = 1;i <= n/2;i++)
            cout << i << " " << n-i << " ";
        cout << endl;
    }
    else if(n % 2 == 0 && k == n/2)
    {
        cout << n << " " << n/2 << " ";
        for(int i = 1;i < n/2;i++)
            cout << i << " " << n - i << " ";
        cout << endl;
    }
    else
        cout << -1 << endl;
}

K. K-Bag
思路;
因为数据太大,所以离散化一下,然后从前面的端点开始枚举,枚举后面的是否满足条件

AC代码

#include 
inline long long read(){char c = getchar();long long x = 0,s = 1;
while(c < '0' || c > '9') {if(c == '-') s = -1;c = getchar();}
while(c >= '0' && c <= '9') {x = x*10 + c -'0';c = getchar();}
return x*s;}
using namespace std;
#define NewNode (TreeNode *)malloc(sizeof(TreeNode))
#define Mem(a,b) memset(a,b,sizeof(a))
#define lowbit(x) (x)&(-x)
const int N = 5e5 + 5;
const long long INFINF = 0x7f7f7f7f7f7f7f;
const int INF = 0x3f3f3f3f;
const double EPS = 1e-7;
const int mod = 1e9 + 7;
const double II = acos(-1);
const double PP = (II*1.0)/(180.00);
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> piil;
int len[N],a[N],b[N],vis[N];
signed main()
{
    std::ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //    freopen("input.txt","r",stdin);
    //    freopen("output.txt","w",stdout);
    int t;
    cin >> t;
    while(t--)
    {
        int n,k,aa = 1;
        cin >> n >> k;
        for(int i = 1;i <= n;i++)
        {
            cin >> a[i];
            b[i] = a[i];
            if(a[i] > k || a[i] <= 0)
                aa = 0;
        }
        if(!aa) {cout << "NO" << endl;continue;}
        sort(b+1,b+n+1);
        int lenb = unique(b+1,b+1+n)-b-1,ans = 1,flag = 0;
        for(int i = 1;i <= n;i++)
            a[i] = lower_bound(b+1,b+lenb+1,a[i])-b;
        for(int i = 1;i <= n;i++)
        {
            while(!vis[a[ans]] && ans <= n)
            {
                vis[a[ans]]++;
                ans++;
            }
            vis[a[i]]--;
            len[i] = ans-i;
//            cout << ans << " " << i << " " << len[i] << endl;
        }
        for(int i = 1;i <= min(k,len[1]+1);i++)
        {
            int q = 1;
            for(int j = i;j <= n;j += k)
            {
                if(j + len[j] > n) continue;
                else if(len[j] != k) {q = 0;break;}
            }
            if(q) {flag = 1;break;}
        }
        if(flag) cout << "YES" << endl;
        else cout << "NO" << endl;
    }
}

你可能感兴趣的:(牛客)