2017.10.16 模拟赛

题目链接

T1

排序后二分

#include <algorithm>
#include <cstdio>
#include <cctype>
#define N 200100

using namespace std;
inline void read(int &x)
{
    bool f=0;register char ch=getchar();
    for(x=0;!isdigit(ch);ch=getchar()) if(ch=='-') f=1;
    for(;isdigit(ch);x=x*10+ch-'0',ch=getchar());
    x=f?-x:x;
}
int n,m,X[N],Y[N];
double B[N],K[N];
bool check(double x1,double y1,int mid)
{
    if(K[mid]*x1+B[mid]>y1) return 0;
    return 1;
}
int main()
{
    freopen("geometry.in","r",stdin);
    freopen("geometry.out","w",stdout);
    read(n);
    for(int i=1;i<=n;i++) read(X[i]);
    for(int i=1;i<=n;i++) read(Y[i]);
    sort(X+1,X+n+1);
    sort(Y+1,Y+n+1);
    for(int i=1;i<=n;i++)
    {
        B[i]=(double)Y[i];
        K[i]=-(double)Y[i]/(double)X[i];
    }
    read(m);
    for(int i=1,x,y;i<=m;i++)
    {
        read(x);read(y);
        int l=1,r=n,ans=0;
        for(int mid;l<=r;)
        {
            mid=(l+r)>>1;
            if(check(x,y,mid)) ans=mid,l=mid+1;
            else r=mid-1;
        }
        printf("%d
",ans);
    }
    fclose(stdin); fclose(stdout);
    return 0;
}
View Code

T2

差分约束做法

记录前缀和S[i],i>=8时首先要满足条件 s[i]-s[i-8]>=a[i]

0<=s[i]-s[i-1]<=b[i]

i<8时有s[23]-s[16+i]+s[i]>=a[i]

因为第三个式子不满足差分约束形式,可以看出s[23]有单调性,可以二分所以可以二分答案当常量处理

Spfa负环则无解

#include<cstring>
#include<cstdio>
int T,a[24],b[24],t[24],ans;
int main()
{
    freopen("cashier.in","r",stdin);
    freopen("cashier.out","w",stdout);
    scanf("%d",&T);
    while(T--)
    {
        memset(t,0,sizeof(t));
        for(int i=0;i<24;i++) scanf("%d",&a[i]);
        for(int i=0;i<24;i++) scanf("%d",&b[i]);
        ans=-1;
        for(int i=0;i<24;i++)
        {
            if(a[i]>t[i])
            {
                int j=i;
                while(a[i]>t[i])
                {
                    if(j+7<i) break;
                    if(j==-1) break;
                    if(b[j]+t[i]>=a[i])
                    {
                        int res=a[i]-t[i];
                        b[j]=b[j]-res;
                        if(j<=16) {for(int k=j;k<=j+7;k++) t[k]+=res;} 
                        else {for(int num=1,k=j;num<=8;++num) t[k]+=res,k=(k+1)%24;}
                        ans+=res;
                        break;
                    }
                    else
                    {
                        int res=b[j];
                        b[j]=0;
                        if(j<=16) {for(int k=j;k<=j+7;k++) t[k]+=res;} 
                        else {for(int num=1,k=j;num<=8;++num) t[k]+=res,k=(k+1)%24;}  
                        ans+=res;
                        j--;
                    }
                }
            }
        }
        if(ans==-1||ans>1000) printf("%d
",ans);
        else printf("%d
",ans+1);
    }
    fclose(stdin); fclose(stdout);
    return 0;
}
考场55分模拟代码
#include <cstdio>
#include <cstdlib>
#include <queue>
#define N 33
using namespace std;

struct edge
{
    int t, n, l;
}e[N * N];
int h[N],tote;
void adde(int u, int v, int l)
{
    e[++tote].t = v;
    e[tote].l = l;
    e[tote].n = h[u];
    h[u] = tote;
    return ;
}
int d[N];
bool inq[N];
bool spfa()
{
    queue<int> Q;
    for (int i = 0; i <= 24; i++) d[i] = -1e9, inq[i] = false;
    d[0] = 0; inq[0] = true; Q.push(0);
    while (!Q.empty())
    {
        int u = Q.front(); Q.pop(); inq[u] = false;
        if (d[u] > 1000) return false;
        for (int i = h[u]; i; i = e[i].n)
        {
            int v = e[i].t, l = e[i].l;
            if (d[v] < d[u] + l)
            {
                d[v] = d[u] + l;
                if (!inq[v])
                {
                    inq[v] = true;
                    Q.push(v);
                }
            }
        }
    }
    return true;
}
int a[30], b[30];
bool solve(int ans)
{
    for (int i = 0; i <= 24; i++) h[i] = 0;
    tote = 0;
    for (int i = 9; i <= 24; i++) adde(i - 8, i, a[i]);
    for (int i = 1; i <= 8; i++) adde(i + 16, i, a[i] - ans);
    for (int i = 1; i <= 24; i++) adde(i - 1, i, 0);
    for (int i = 1; i <= 24; i++) adde(i, i - 1, -b[i]);
    adde(0, 24, ans); adde(24, 0, -ans);
    return spfa();
}
int main(int argc, char ** argv)
{
    freopen("cashier.in", "r", stdin);
    freopen("cashier.out", "w", stdout);
    int test;
    scanf("%d", &test);
    for (int i = 1; i <= test; i++)
    {
        for (int i = 1; i <= 24; i++) scanf("%d", &a[i]);
        for (int i = 1; i <= 24; i++) scanf("%d", &b[i]);
        int ans = 0;
        while (true)
        {
            if (++ans > 1000)
            {
                ans = -1; break;
            }
            if (solve(ans)) break;
        }
        printf("%d
", ans);
    }
    fclose(stdin);
    fclose(stdout);
    return 0;
}
std

T3

线段树

部分分可以dp f[i][j]表示前i个数选了j个的答案

f[i][j]=f[i-1][j]+f[i-1][j-1]*a[i] (i选不选)

k比较小,所以线段树每个节点维护一个区间答案记为f[i]

考虑一段区间i,左边取j个右边就取i-j个 答案是每个方案的左边乘右边的和。

就是i左儿子f[j]和右边的f[i-j] 所以f[i]=Σ(j=0~i) lc f[j]*rc f[i-j]

考虑取反操作,i是奇数就取反,偶数无影响(因为是相乘)

考虑区间加, 开始f[i] a1*a2……an  后来是(a1+c)*(a2+c)……(an+c)

考虑类似二项式定理,当上述a1~an  n个方案如果取了j个了,分别为al1,al2……alj

那考虑最后答案,如果已经选了j个方案是(al1+c)(al2+c)……(alj+c)再还能选i-j个 最后答案是C(len-i,i-j)*f[j]*c^(i-j)

复杂度 O(k^2*nlogn)

#include <algorithm>
#include <cstdio>
#include <cctype>
#define Mod 1000000007
typedef long long LL;
#define BUF 12312312
LL n,m,ans,z,a[50005];
char Buf[BUF],*buf=Buf;
inline void read(LL &x)
{
    bool f=0;
    for(x=0;!isdigit(*buf);++buf) if(*buf=='-') f=1;
    for(;isdigit(*buf);x=x*10+*buf-'0',++buf);
    x=f?(-x):x;
}
void dfs(LL l,LL r,LL num,LL sc)
{
    if(num==z)
    {
        ans=(ans+sc+Mod)%Mod;
        return;
    }
    for(int i=l;i<=r;++i) dfs(i+1,r,num+1,(sc*a[i]+Mod)%Mod);
}
int main(int argc,char *argv[])
{
    freopen("game.in","r",stdin);
    freopen("game.out","w",stdout);
    fread(buf,1,BUF,stdin);
    read(n),read(m);
    if(n<=100||m<=100)
    {
        for(int i=1;i<=n;++i) read(a[i]);
        for(LL opt,x,y;m--;)
        {
            read(opt),read(x);read(y);
            if(opt==2) {for(int i=x;i<=y;++i) a[i]=-a[i];} 
            if(opt==1) {read(z);for(int i=x;i<=y;++i) a[i]=(a[i]+z+Mod)%Mod;}
            if(opt==3)
            { 
                read(z);
                ans=0;dfs(x,y,0,1);
                printf("%I64d
",(ans+Mod)%Mod);
            }
        }
    }
    else
    {
        puts("hello ladies and gentlemen");
        puts("i'm MC bytlxmdsyl");
        puts("有一本书名叫天方夜谭");
        puts("很奇妙又好看");
        puts("叙述的是阿拉伯的故事");
        puts("到处都在流传");
        puts("由阿拉丁神灯");
        puts("有辛巴达航海");
        puts("one two three and four");
        puts("come on yo let's go");
        puts("这里有个神奇的故事");
        puts("一个人 一个人");
        puts("一个人的命运会改变");
        puts("阿里 阿里巴巴");
        puts("阿里巴巴是个快乐的青年");
        puts("阿里 阿里巴巴");
        puts("阿里巴巴是个快乐的青年");
        puts("#芝麻开门#");
    }
    fclose(stdin); fclose(stdout);
    return 0;
}
考场30分暴力代码
#include <cstdio>
#include <cstdlib>
#define MOD 1000000007
#define N 100005
typedef long long LL; 
using namespace std;

struct Node
{
    LL f[11];
}node[N * 4];
LL a[N], lazy1[N * 4];
bool lazy2[N * 4];
LL C[N][11];
Node merge(Node lc, Node rc)
{
    Node o;
    o.f[0] = 1;
    for (int i = 1; i <= 10; i++)
    {
        o.f[i] = 0;
        for (int j = 0; j <= i; j++)
            o.f[i] = (o.f[i] + lc.f[j] * rc.f[i - j] % MOD) % MOD;
    }
    return o;
}
void build(int o, int l, int r)
{
    if (l == r)
    {
        for (int i = 0; i <= 10; i++) node[o].f[i] = 0;
        node[o].f[0] = 1;
        node[o].f[1] = (a[l] % MOD + MOD) % MOD;
        return ;
    }
    int mid = (l + r) >> 1;
    build(o * 2, l, mid);
    build(o * 2 + 1, mid + 1, r);
    node[o] = merge(node[o * 2], node[o * 2 + 1]);
    return ;
}
void update1(int o, int l, int r, int c)
{
    int len = r - l + 1;
    LL ff[11];
    for (int i = 0; i <= 10; i++) ff[i] = node[o].f[i];
    for (int i = 1; i <= 10; i++)
    {
        node[o].f[i] = 0;
        LL t = 1;
        for (int j = 0; j <= i; j++)
        {
            LL tmp = ff[i - j] * C[len - (i - j)][j] % MOD * t % MOD;
            node[o].f[i] = (node[o].f[i] + tmp) % MOD;
            t = t * c % MOD;
        }
    }
    return ;
}
void push_down(int o, int l, int r)
{
    int mid = (l + r) >> 1;
    if (lazy1[o])
    {
        if (lazy2[o * 2])
            lazy1[o * 2] = (lazy1[o * 2] + MOD - lazy1[o]) % MOD;
        else 
            lazy1[o * 2] = (lazy1[o * 2] + lazy1[o]) % MOD;
        if (lazy2[o * 2 + 1])
            lazy1[o * 2 + 1] = (lazy1[o * 2 + 1] + MOD - lazy1[o]) % MOD;
        else 
            lazy1[o * 2 + 1] = (lazy1[o * 2 + 1] + lazy1[o]) % MOD;
        update1(o * 2, l, mid, lazy1[o]);
        update1(o * 2 + 1, mid + 1, r, lazy1[o]);
        lazy1[o] = 0;
    }
    if (lazy2[o])
    {
        lazy2[o * 2] ^= 1;
        lazy2[o * 2 + 1] ^= 1;
        for (int j = 1; j <= 10; j += 2)
        {
            node[o * 2].f[j] = MOD - node[o * 2].f[j];
            node[o * 2 + 1].f[j] = MOD - node[o * 2 + 1].f[j];
        }
        lazy2[o] = 0;
    }
}
void modify1(int o, int l, int r, int ll, int rr, int c)
{
    if (ll <= l && rr >= r)
    {
        if (lazy2[o]) lazy1[o] = (lazy1[o] + MOD - c) % MOD;
        else lazy1[o] = (lazy1[o] + c) % MOD;
        update1(o, l, r, c);
        return ;
    }
    int mid = (l + r) >> 1;
    push_down(o, l, r);
    if (ll <= mid) modify1(o * 2, l, mid, ll, rr, c);
    if (rr > mid) modify1(o * 2 + 1, mid + 1, r, ll, rr, c);
    node[o] = merge(node[o * 2], node[o * 2 + 1]);
    return ;
}
void modify2(int o, int l, int r, int ll, int rr)
{
    if (ll <= l && rr >= r)
    {
        for (int i = 1; i <= 10; i += 2) node[o].f[i] = MOD - node[o].f[i];
        lazy2[o] ^= 1;
        return ;
    }
    int mid = (l + r) >> 1;
    push_down(o, l, r);
    if (ll <= mid) modify2(o * 2, l, mid, ll, rr);
    if (rr > mid) modify2(o * 2 + 1, mid + 1, r, ll, rr);
    node[o] = merge(node[o * 2], node[o * 2 + 1]);
    return ;
}
Node query(int o, int l, int r, int ll, int rr)
{
    if (ll <= l && rr >= r) 
        return node[o];
    int mid = (l + r) >> 1;
    push_down(o, l, r);
    if (rr <= mid) return query(o * 2, l, mid, ll, rr);
    if (ll > mid) return query(o * 2 + 1, mid + 1, r, ll, rr);
    Node lc = query(o * 2, l, mid, ll, rr);
    Node rc = query(o * 2 + 1, mid + 1, r, ll, rr);
    return merge(lc, rc);
}
int main(int argc, char ** argv)
{
    freopen("game.in", "r", stdin);
    freopen("game.out", "w", stdout);
    int n, m;
    scanf("%d %d", &n, &m);
    C[0][0] = 1;
    for (int i = 1; i <= n; i++)
    {
        C[i][0] = 1;
        for (int j = 1; j <= 10; j++) 
            C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % MOD;
    }
    for (int i = 1; i <= n; i++) 
        scanf("%d", &a[i]);
    build(1, 1, n); 
    for (int i = 1; i <= m; i++)
    {

        int l, r, opt;
        scanf("%d%d%d",&opt, &l, &r);
        if (opt == 1)
        {
            int c;
            scanf("%d", &c);
            c = (c % MOD + MOD) % MOD;
            modify1(1, 1, n, l, r, c);
        }
        else if (opt == 2)
        {
            modify2(1, 1, n, l, r);
        }
        else
        {
            int k;
            scanf("%d", &k);
            Node o = query(1, 1, n, l, r);
            printf("%d
", o.f[k] % MOD);
        }
    }
    return 0;
}
std
原文地址:https://www.cnblogs.com/ruojisun/p/7678419.html