2017-10-25 NOIP模拟赛

1 任务安排


manage.in/.out/.cpp
1.1 问题描述
你有 N 个工作,同一时刻只能做一个任务, 其中每个工作有其所需时
间, 及完成的 Deadline(截止时间), 问要完成所有工作, 最迟要从什么时候开
始。
你最早可以从时间 0 开始工作。
1.2 输入格式
第一行一个整数 N,表示任务数量
接下来 n 行,每行两个整数,T i ,S i ,分别表示该任务的持续时间和截
止时间。
1.3 输出格式
输出一个整数,表示最晚的开始时间,如果不能完成,输出-1。
1.4 样例输入
4
3 5
8 14
5 20
1 16
1.5 样例输出
2
1.6 数据规模及约定
对于 40% 的数据,N <= 20
对于 60% 的数据,N <= 1000
对于 100% 的数据,1<= N <= 100000
1<= T i <= 100000
1<= S i <= 1000000

#include<iostream>
#include<cstdio>
#include<algorithm>
#define maxn 100001
using namespace std;
int n,pos;
struct node{
    int t,s;
    bool operator < (const node b)const{
        return s<b.s;
    }
}a[maxn];
int main(){
    freopen("manage.in","r",stdin);freopen("manage.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d%d",&a[i].t,&a[i].s);
    sort(a+1,a+n+1);
    pos=a[n].s;
    for(int i=n;i>=1;i--){
        pos=min(pos,a[i].s);
        pos-=a[i].t;
    }
    if(pos<0)puts("-1");
    else printf("%d",pos);
}
100分 贪心


2 小 a 的强迫症


qiang.in/.out/.cpp
2.1 问题描述
小 a 是一名强迫症患者,现在他要给一群带颜色的珠子排成一列,现在
有 N 种颜色,其中第 i 种颜色的柱子有 num(i) 个。要求排列中第 i 种颜色
珠子的最后一个珠子,一定要排在第 i+1 种颜色的最后一个珠子之前。问
有多少种排列珠子的方案。
2.2 输入格式
第一行一个整数 N,表示珠子颜色数量
第二行 N 个整数,分别表示每种珠子的颜色数量
2.3 输出格式
排列方案数,对 998244353 取余
2.4 样例输入
3
2 2 1
2.5 样例输出
3
2.6 数据规模及约定
共 3 种排列方案:
1 2 1 2 3
1 1 2 2 3
2 1 1 2 3
对于 40% 的数据,所有珠子数量和小于 15
对于 80% 的数据,N <= 1000,所有珠子数量和小于 5000
对于 100% 的数据,N <= 100000,所有珠子数量和小于 500000

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 100100
#define MAXM 501000
#define mod 998244353
using namespace std;
int n,col[MAXN];
long long ans,sum,tot;
long long C[5010][5010];
int main(){
    //freopen("qiang.in","r",stdin);freopen("qiang.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&col[i]);
        tot+=col[i];
    }
    C[0][0]=1;
    for(int i=1;i<=tot;i++)
        for(int j=0;j<=i;j++)
            C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
    ans=1;sum=0;
    for(int i=1;i<=n;i++){
        ans=ans*C[sum+col[i]-1][col[i]-1]%mod;
        sum+=col[i];
    }
    cout<<ans<<endl;
}
80分 组合数学
#include<iostream>
#include<cstdio>
#include<cstring>

#define N 1000007
#define mod 998244353
#define ll long long

using namespace std;
ll n,m,ans,cnt;
ll f[N]={1,1},fac[N]={1,1},inv[N]={1,1};
ll num[N],sum[N];

inline ll read()
{
    ll x=0,f=1;char c=getchar();
    while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}

void init()
{
    for(int i=2;i<=N;i++)
    {
        fac[i]=(fac[i-1]%mod*i%mod)%mod;
        f[i]=(mod-mod/i)*f[mod%i]%mod;
        inv[i]=inv[i-1]*f[i]%mod;
    }
}

ll C(int a,int b)
{
    if(a<b) return 1;
    return fac[a]%mod*inv[b]%mod*inv[a-b]%mod;
}

int main()
{
    freopen("qiang.in","r",stdin);
    freopen("qiang.out","w",stdout);
    n=read();
    for(int i=1;i<=n;i++) 
      num[i]=read(),sum[i]=sum[i-1]+num[i];
    init();ans=1;
    for(int i=2;i<=n;i++)
    {
        ans=(ans%mod*C(sum[i]-1,num[i]-1)%mod)%mod;
        ans%=mod;
    }
    cout<<ans%mod<<endl;
    fclose(stdin);fclose(stdout);
    return 0;
}
100分 逆元求组合数

3 函数求和


sum.in/.out/.cpp
3.1 问题描述
你有一个含 N 个数字的数组 A,元素标号 1 到 N,同时他也有 N 个函
数,也标号 1 到 N。
第 i 个函数会返回数组中标号 L i 和 R i 之间的元素的和。
现在有以下两种询问:
1 x y 将数组的第 x 个元素修改为 y。
2 m n 询问标号在 m 和 n 之间的函数的值的和。
3.2 输入格式
输入数据第一行包含一个整数 N,表示数组的长度和函数的数量。
接下来的一行包含 N 个整数,表示数组中的元素 A i 。
接下来的 N 行,每行包含两个整数 L i ,R i ,表示一个函数。
接下来一行包含一个整数 Q,表示询问次数。
下面 Q 行,每行一个询问,格式见题目描述。
3.3 输出格式
对于每个第 2 类询问,输出相应的答案。
3.4 样例输入
5
1 2 3 4 5
1 3
2 5
4 5
3 5
1 2
4
2 1 4
1 3 7
2 1 4
2 3 5

3.5 样例输出
41
53
28
3.6 数据规模及约定
对于前 20% 的数据: N ≤ 1000,Q ≤ 1000
对于另外 30% 的数据: R i − L i ≤ 10, 所有的 x 各不相同
对于 100% 的数据: 1 ≤ N ≤ 10 5 , 1 ≤ L i ≤ R i ≤ N, 1 ≤ x ≤ N,
1 ≤ m ≤ n ≤ N, 1 ≤ A i ,y ≤ 10 9 , 1 ≤ Q ≤ 10

#include<iostream>
#include<cstdio>
#include<vector>
#include<ctime>
#define maxn 100010
#ifdef WIN32
#define PLL "%I64d"
#else
#define PLL "%lld"
#endif
using namespace std;
vector<int>to[100010];
long long tr1[maxn<<4],a[maxn];
struct node{
    int l,r;
}f[maxn];
int n,q;
void add1(int pos,int del){
    while(pos<=n){
        tr1[pos]+=del;
        pos+=(pos&-pos);
    }
}
long long query1(int pos){
    long long res=0;
    while(pos){
        res+=tr1[pos];
        pos-=(pos&-pos);
    }
    return res;
}
int main(){
    //freopen("Cola.in","r",stdin);
    freopen("sum.in","r",stdin);freopen("sum.out","w",stdout);
    scanf("%d",&n);
    int op,x,y;
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        add1(i,a[i]);
    }
    int l,r;
    for(int i=1;i<=n;i++)scanf("%d%d",&f[i].l,&f[i].r);
    scanf("%d",&q);
    while(q--){
        scanf("%d%d%d",&op,&x,&y);
        if(op==1){
            add1(x,y-a[x]);
            a[x]=y;
        }
        else {
            long long ans=0;
            for(int i=x;i<=y;i++){
                ans+=query1(f[i].r)-query1(f[i].l-1);
            }
            printf(PLL"
",ans);
        }
    }
    //cout<<endl<<clock();
}
20分 树状数组
原文地址:https://www.cnblogs.com/thmyl/p/7727904.html