牛客练习赛25

传送

A题 因数个数和

例如n=10,  那么从1,到10  所有数字都含因子1    2,4,6,8,10含因子2   3,6,9含因子3  依次类推

枚举不同因子  计算加和

#include 
#define repu(i,s,e) for(int i = s;i <= e; ++i)
#define repd(i,s,e) for(int i = s;i >= e; --i)
#define pb push_back
#define emb emplace_back
#define mst(arr, v) memset(arr, v, sizeof(arr))
#define close_ios ios::sync_with_stdio(false)
#define close_cin cin.tie(0)
#define close_cout cout.tie(0)
#define ct(a) cout<>T;while(T--)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair Pa;
typedef vector Ve;
const double PI = acos(1.0);
const double eps = 1e-8;
int dir[4][2] = {{0,1},{0,-1},{-1,0},{1,0}};
const int INF = 0x3f3f3f3f;
const int N = 1e5 + 5;
const int M = 100 + 5;
const int mod = 1e9 + 7;

int main()
{
    Repeat{

        int n;

        ll ans = 0;

        sf1(n);

        int pos;

        for(int i = 1;i <= n;i = pos + 1)
        {
            pos = n / (n / i);

            ans += 1LL * (pos - i + 1) * (n / i);

        }
        ct(ans);
    }
    return 0;
}

 

B题

(开始我竟然想的是m次LIS。。 )

记录下所有的值a[i], 设置一个数组 f 记录 第i个所长最长序列的长度  再设置一个数组cnt 记录  长度为f[i]的有多少个

询问时直接从100往小找即可,题中明确ai小于100  所以最大长度不超过100

每次修改影响a[x]的值 及影响f[x] 及以后的 min(x+100,n)项  原来的f[i]的数量要减1  后来f[i] 要加1

#include 
#define repu(i,s,e) for(int i = s;i <= e; ++i)
#define repd(i,s,e) for(int i = s;i >= e; --i)
#define pb push_back
#define emb emplace_back
#define mst(arr, v) memset(arr, v, sizeof(arr))
#define close_ios ios::sync_with_stdio(false)
#define close_cin cin.tie(0)
#define close_cout cout.tie(0)
#define ct(a) cout<>T;while(T--)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair Pa;
typedef vector Ve;
const double PI = acos(1.0);
const double eps = 1e-8;
int dir[4][2] = {{0,1},{0,-1},{-1,0},{1,0}};
const int INF = 0x3f3f3f3f;
const int N = 1e5 + 5;
const int M = 100 + 5;
const int mod = 1e9 + 7;

int n, m, a[N], f[N], cnt[M];

int query()
{
    repd(i,100,1)
        if(cnt[i]) return i;

    return 0;
}
int main()
{
    sf2(n, m);

    repu(i,1,n)
    {
        sf1(a[i]);
        if(a[i] > a[i - 1]) f[i] = f[i - 1] + 1;
        else f[i] = 1;
        cnt[f[i]] ++;
    }

    ct(query());

    int x, y;
    while(m --)
    {
        sf2(x,y);

        a[x] = y;

        repu(i,x,min(x+100,n))
        {
            int t = 1;
            if(a[i] > a[i - 1])
                t = f[i- 1] + 1;

            cnt[f[i]] --;
            f[i] = t;
            cnt[f[i]]++;
        }

        ct(query());
    }

    return 0;
}

线段树做法:

#include 
#define repu(i,s,e) for(int i = s;i <= e; ++i)
#define repd(i,s,e) for(int i = s;i >= e; --i)
#define pb push_back
#define emb emplace_back
#define mst(arr, v) memset(arr, v, sizeof(arr))
#define close_ios ios::sync_with_stdio(false)
#define close_cin cin.tie(0)
#define close_cout cout.tie(0)
#define ct(a) cout<>T;while(T--)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair Pa;
typedef vector Ve;
const double PI = acos(1.0);
const double eps = 1e-8;
int dir[4][2] = {{0,1},{0,-1},{-1,0},{1,0}};
const int INF = 0x3f3f3f3f;
const int N = 1e5 + 5;
const int M = 100 + 5;
const int mod = 1e9 + 7;
int n, m;
int a[N];
int lsum[N<<2], rsum[N<<2], msum[N<<2];

void pushup(int l,int r,int rt)
{
    int m = (l+r)>>1;

    lsum[rt] = lsum[rt<<1];
    rsum[rt] = rsum[rt<<1|1];
    msum[rt] = max(msum[rt<<1], msum[rt<<1|1]);

    if(a[m] < a[m+1]) //如果左区间的右端小于右区间的左端
    {
        if(lsum[rt<<1] == m - l + 1) //如果左区间全部为上升序列
            lsum[rt] = lsum[rt<<1] + lsum[rt<<1|1];
        if(rsum[rt<<1|1] == r - m)  //如果右区间全部为上升序列
            rsum[rt] = rsum[rt<<1] + rsum[rt<<1|1];

        msum[rt] = max(msum[rt], lsum[rt<<1|1] + rsum[rt<<1]);
    }
}

void build(int l,int r,int rt)
{
    if(l == r)
    {
        lsum[rt] = rsum[rt] = msum[rt] = 1;
        return ;
    }

    int m = (l+r)>>1;

    build(lson);
    build(rson);

    pushup(l,r,rt);
}

void update(int p,int c,int l, int r,int rt)
{
    if(l == r)
    {
        a[p] = c;
        return ;
    }

    int m = (l+r)>>1;

    if(p <= m)
        update(p,c,lson);
    else
        update(p,c,rson);

    pushup(l,r,rt);
}

int query(int L,int R,int l,int r,int rt)
{
    if(l >= L && R >= r)
        return msum[rt];

    int ret = 0;
    int m = (l+r)>>1;

    if(L <= m) ret = max(ret, query(L,R,lson));

    if(R > m) ret = max(ret, query(L,R,rson));

    //如果左区间的右端小于右区间左端
    if(a[m] < a[m + 1])
        ret = max(ret, min(m - L + 1, rsum[rt<<1]) + min(R - m, lsum[rt<<1|1]));

    return ret;
}

int main()
{
    sf2(n, m);

    repu(i,1,n)
        sf1(a[i]);

    build(1,n,1);

    ct(query(1,n,1,n,1));

    while(m --)
    {
        int x, y;

        sf2(x, y);

        update(x,y,1,n,1);

        ct(query(1,n,1,n,1));
    }
    return 0;
}

C题

看例子,四项和是 10  而第一次变换之后是 前一次变换的和 减去当前位置的值

第二次变换时,起始是20 + a[i]  而 20 = (n - 1)*change[i-1] - 没有变换时的值

以此类推,你会发现他是一个等比数列,加减原来的值与变换的次数有关系

(逻辑混乱。。。)

下面贴一下官方的解

牛客练习赛25_第1张图片

#include 
#define repu(i,s,e) for(int i = s;i <= e; ++i)
#define repd(i,s,e) for(int i = s;i >= e; --i)
#define pb push_back
#define emb emplace_back
#define mst(arr, v) memset(arr, v, sizeof(arr))
#define close_ios ios::sync_with_stdio(false)
#define close_cin cin.tie(0)
#define close_cout cout.tie(0)
#define ct(a) cout<>T;while(T--)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair Pa;
typedef vector Ve;
const double PI = acos(1.0);
const double eps = 1e-8;
int dir[4][2] = {{0,1},{0,-1},{-1,0},{1,0}};
const int INF = 0x3f3f3f3f;
const int N = 1e5 + 5;
const int M = 100 + 5;
const int mod = 1e9 + 7;

int n, m;
int a[N];
ll ans[N];
int main()
{
    ll s = 0;

    sf2(n, m);

    repu(i,1,n)
        sf1(a[i]), s += a[i], s%= mod;

    s %= mod;

    ans[1] = s;

    repu(i,2,1e5)
    {
        if(i&1)
            ans[i] = ((n - 1) * ans[i - 1] % mod + s + mod)% mod;
        else
            ans[i] = ((n - 1) * ans[i - 1] % mod - s + mod)% mod ;
    }

    int p, t;

    repu(i,1,m)
    {
        sf2(p,t);

        if(!t)
        {
            ct(a[p]);
            continue;
        }

        if(t&1)
            ct((ans[t] - a[p] + mod)%mod);
        else
            ct((ans[t] + a[p] + mod)%mod);
    }
    return 0;
}

 

你可能感兴趣的:(牛客网,牛客比赛)