101Hack44

28 篇文章 0 订阅
19 篇文章 0 订阅

1001——Picking Numbers

Picking Numbers题目
水题,差小于1的两个数的个数最大

#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;

int arr[110];
int main() {
    int n,data;
    scanf("%d",&n);
    for(int i = 0;i<n;i++) {
        scanf("%d",&data);
        arr[data]++;
    }
    int ans = arr[0];
    for(int i = 0;i<100;i++) ans =max(ans,arr[i]+arr[i+1]);
    printf("%d\n",ans);
    return 0;
}

1002——Alice and Bob’s Silly Game

Alice and Bob’s Silly Game题目
博弈的问题,给你n个数,每次可以选择一个素数,将素数和素数的倍数的数删除,如果不能删除则为输。我们会发现这个题的本质就是给你小于的n的素数,每次可以从中选择一个素数删除,直到不能删除为止。那么如果素数的个数为奇数则Alice赢,否则Bob赢。

#include <bits/stdc++.h>

using namespace std;
const int maxn=1e5+100;
int vis[maxn];
void Get() {
    memset(vis,1,sizeof(vis));
    vis[0] = vis[1] = 0;
    for(int i = 2;i<maxn;i++) {
        if(vis[i]) {
            for(int j = i+i;j<maxn;j+=i) vis[j] = 0;
        }
    }
    for(int i = 0;i<maxn;i++) vis[i] = vis[i]+vis[i-1];
}
int main() {
    Get();
    int n,T;
    scanf("%d",&T);
    while(T--) {
        scanf("%d",&n);
        if(vis[n]&1) printf("Alice\n");
        else printf("Bob\n");
    }
    return 0;
}

1003——Expected Tree Leaves

Expected Tree Leaves题目
将节点从小到大放置,每次选择一个小的节点放在他的后面,问形成的树的叶子节点的个数的期望
我们计算第i个节点为叶子节点的期望,那么我们假设 i i i为叶子节点,那么第 i + 1 i+1 i+1的节点的概率为 i − 1 i \frac{i-1}{i} ii1,第 i + 2 i+2 i+2的节点的概率为 i i + 1 \frac{i}{i+1} i+1i,那么第 i i i个节点为叶子的概率为 P i = i − 1 i × i i + 1 + ⋯ + n − 2 n − 1 = i − 1 n − 1 P_i = \frac{i-1}{i}\times \frac{i}{i+1}+\cdots+\frac{n-2}{n-1} = \frac{i-1}{n-1} Pi=ii1×i+1i++n1n2=n1i1,所以 E = ∑ i = 2 n = 1 n − 1 + 2 n − 1 + ⋯ + n − 1 n − 1 = ∑ i = 1 n − 1 n − 1 = n × ( n − 1 ) 2 n − 1 = n 2 E = \sum\limits_{i=2}^n=\frac{1}{n-1}+\frac{2}{n-1} + \cdots+\frac{n-1}{n-1} = \frac{\sum\limits_{i=1}^{n-1}}{n-1} = \frac{\frac{n\times(n-1)}{2}}{n-1} = \frac{n}{2} E=i=2n=n11+n12++n1n1=n1i=1n1=n12n×(n1)=2n,所以 a n s = n 2 × n ! ans = \frac{n}{2}\times n! ans=2n×n!

#include <bits/stdc++.h>

using namespace std;
const int mod = 1e9+7;
typedef long long LL;
int main() {
    int n;
    LL ans;
    scanf("%d",&n);
    ans = n;
    for(int i = 3;i<=n;i++) ans = (ans*i)%mod;
    printf("%lld\n",ans);
    return 0;
}

1004——Palindromic Subsets

Palindromic Subsets 题目
给你一个字符串,有两种操作,一种是对于区间[L,R]中的字符,向后移动T个字符既 C i = ( C i + 26 ) % 26 C_i = (C_i+26)\%26 Ci=(Ci+26)%26,第二种操作是询问区间[L,R]可以组成多少个回文串
对于一个区间,我们对于第一种操作,可以通过线段树实现,那么对于第二种操作,我们假设已经知道区间[L,R]种每一个字符的个数 N u m i   0 ≤ i ≤ 25 Num_i\ 0\le i \le 25 Numi 0i25,对于一个字母 i i i可以组成多少个回文串呢?显然是 2 N u m i 2^{Num_i} 2Numi个,其中长度为奇数和偶数的个数相同均为 2 N u m i − 1 2^{Num_i-1} 2Numi1种。显然最后组成的回文串分为两种,一种是长度为奇数的,一种是长度为偶数的。对于长度为偶数的,答案就是多有字符组成长度为偶数的个数的乘积,奇数就是我们枚举长度为奇数的字符串,那么答案就是非枚举字符的偶数的乘积与枚举字符的奇数乘积。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e5+100;
const int mod = 1e9+7;
struct node {
    int lazy;
    int num[26];
    void Clear() {
        lazy = 0;
        memset(num,0,sizeof(num));
    }
}tr[maxn*5];
char str[maxn];
int Pow[maxn];
int suffix[30],prefix[30],odd[30],even[30];
int n,q;
node  ans;
void pushup(int st) {
    for(int i = 0;i<26;i++) tr[st].num[i] = tr[st<<1].num[i]+tr[st<<1|1].num[i];
}
void build(int L,int R,int st) {
    tr[st].Clear();
    if(L==R) {
        tr[st].num[str[L-1] - 'a']++;
        return ;
    }
    int mid = (L+R) >>1;
    build(L,mid,st<<1);
    build(mid+1,R,st<<1|1);
    pushup(st);
}
node Rotate(node a,int b) {
    node ans; ans.Clear();
    ans.lazy = a.lazy;
    for(int i = 0;i<26;i++) ans.num[(i+b)%26] = a.num[i];
    return ans;
}
void pushdown(int L,int R,int st) {
    if(L==R || tr[st].lazy == 0) return ;
    tr[st<<1].lazy = (tr[st<<1].lazy+tr[st].lazy)%26;
    tr[st<<1|1].lazy =(tr[st<<1|1].lazy+tr[st].lazy)%26;
    tr[st<<1] = Rotate(tr[st<<1],tr[st].lazy);
    tr[st<<1|1] = Rotate(tr[st<<1|1],tr[st].lazy);
    tr[st].lazy = 0;
}
void Update(int L,int R,int st,int l,int r,int tm) {
    if(l<=L && R<=r) {
        tr[st].lazy = (tr[st].lazy+tm)%26;
        tr[st] = Rotate(tr[st],tm);
        return ;
    }
    pushdown(L,R,st);
    int mid = (L+R) >>1;
    if(l<=mid) Update(L,mid,st<<1,l,r,tm);
    if(r> mid) Update(mid+1,R,st<<1|1,l,r,tm);
    pushup(st);
}
void Query(int L,int R,int st,int l,int r) {
    if(l<=L && R<=r) {
        for(int i = 0;i<26;i++) ans.num[i] = ans.num[i]+tr[st].num[i];
        return ;
    }
    pushdown(L,R,st);
    int mid = (L+R)>>1;
    if(l<=mid) Query(L,mid,st<<1,l,r);
    if(r>mid)  Query(mid+1,R,st<<1|1,l,r);
    pushup(st);
}
int Count() {
    int ant = 1;
    for(int i = 0;i<26;i++) {
        if(ans.num[i] ==0) {
            odd[i] = 0;
            even[i] = 1;
        }
        else {
            odd[i]  = Pow[ans.num[i]-1];
            even[i] = Pow[ans.num[i]-1];
        }
    }
    prefix[0] = even[0];
    for(int i = 1;i<26;i++) prefix[i] = (prefix[i-1]*1LL*even[i])%mod;
    suffix[25] = even[25];
    for(int i = 24;i>=0;i--) suffix[i] = (suffix[i+1]*1LL*even[i])%mod;
    ant = prefix[25];
    for(int i = 0;i<26;i++) {
        int cur = ((i == 0?1:prefix[i-1])*1LL*(i==25?1:suffix[i+1]))%mod;
        cur = (cur*1LL*odd[i])%mod;
        ant = (ant+cur)%mod;
    }
    return (ant-1+mod)%mod;
}
int main() {
    scanf("%d %d",&n,&q);
    int op,l,r,tm;
    Pow[0] = 1;
    for(int i = 1;i<maxn;i++) Pow[i] = (Pow[i-1]<<1)%mod;
    scanf("%s",str);
    build(1,n,1);
    while(q--) {
        scanf("%d %d %d",&op,&l,&r);
        if(op == 1) scanf("%d",&tm);
        l++,r++;
        if(op == 1) {
            Update(1,n,1,l,r,tm%26);
        }
        else {
            ans.Clear();
            Query(1,n,1,l,r);
            printf("%d\n",Count());
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值