首页 > 代码库 > noip2013 提高组

noip2013 提高组

T1 转圈游戏 题目传送门

果不其然 第一题还是模拟题 一波快速幂解决问题

技术分享
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int read(){
    int ans=0,f=1,c=getchar();
    while(c<0||c>9){if(c==-) f=-1; c=getchar();}
    while(c>=0&&c<=9){ans=ans*10+(c-0); c=getchar();}
    return ans*f;
}
int n,m,k,x;
int qmod(int a,int b,int c){
    int ans=1;
    while(b){
        if(b&1) ans=ans*a%c;
        b=b/2;
        a=a*a%c;
    }
    return ans;
}
int main()
{
    n=read(); m=read(); k=read(); x=read(); 
    int v=qmod(10,k,n);
    printf("%d\n",(v*m+x)%n);
    return 0;
}
View Code

T2 火柴排队 题目传送门

 这是道树状数组求逆序数对的题目 当然还要加一波离散化就好了 不过这题的离散化很玄学哇 2333

技术分享
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
const int M=100007,mod=99999997;
int read(){
    int ans=0,f=1,c=getchar();
    while(c<0||c>9){if(c==-) f=-1; c=getchar();}
    while(c>=0&&c<=9){ans=ans*10+(c-0); c=getchar();}
    return ans*f;
}
struct node{int w,pos;}a[M],b[M];
bool cmp(node a,node b){return a.w<b.w;}
int c[M],sum[M],n;
LL ans;
int lowbit(int x){return x&-x;}
void insert(int x){
    while(x<=n){
        sum[x]++;
        x+=lowbit(x);
    }
}
int push_sum(int x){
    int ans=0;
    while(x){ans+=sum[x]; x-=lowbit(x);}
    return ans;
}
int main()
{
    n=read(); 
    for(int i=1;i<=n;i++) a[i].w=read(),a[i].pos=i;
    for(int i=1;i<=n;i++) b[i].w=read(),b[i].pos=i;
    sort(a+1,a+1+n,cmp); sort(b+1,b+1+n,cmp);
    for(int i=1;i<=n;i++) c[a[i].pos]=b[i].pos;
    for(int i=1;i<=n;i++){
        insert(c[i]);
        ans=(ans+i-push_sum(c[i]))%mod;
    }
    printf("%lld\n",ans);
    return 0;
}
View Code

T3 货车运输 题目传送门

几乎是裸的lca吧 用lca维护一波最近公共祖先和路径最小值就好了

技术分享
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int M=150007; 
int read(){
    int ans=0,f=1,c=getchar();
    while(c<0||c>9){if(c==-) f=-1; c=getchar();}
    while(c>=0&&c<=9){ans=ans*10+(c-0); c=getchar();}
    return ans*f;
}
int w[M],n,f[M][2]; 
int main()
{
    n=read();
    for(int i=1;i<=n;i++) w[i]=read(),f[i][0]=f[i][1]=1;
    for(int i=1;i<=n;i++)
        for(int j=i-1;j;j--){
            if(w[i]>w[j]) f[i][1]=max(f[i][1],f[j][0]+1);
            if(w[j]>w[i]) f[i][0]=max(f[i][0],f[j][1]+1);
            if(f[i][0]!=1&&f[i][1]!=1) break;
        }
    printf("%d\n",max(f[n][0],f[n][1]));
    return 0;
}
View Code

T4 积木大赛  题目传送门

这道题就是我们只考虑相邻两列h1 h2 容易证明他的无后效性

技术分享
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int M=150007; 
int read(){
    int ans=0,f=1,c=getchar();
    while(c<0||c>9){if(c==-) f=-1; c=getchar();}
    while(c>=0&&c<=9){ans=ans*10+(c-0); c=getchar();}
    return ans*f;
}
int w[M],n,f[M][2]; 
int main()
{
    n=read();
    for(int i=1;i<=n;i++) w[i]=read(),f[i][0]=f[i][1]=1;
    for(int i=1;i<=n;i++)
        for(int j=i-1;j;j--){
            if(w[i]>w[j]) f[i][1]=max(f[i][1],f[j][0]+1);
            if(w[j]>w[i]) f[i][0]=max(f[i][0],f[j][1]+1);
            if(f[i][0]!=1&&f[i][1]!=1) break;
        }
    printf("%d\n",max(f[n][0],f[n][1]));
    return 0;
}
View Code

T5 花匠 题目传送门

正解似乎是算拐点+1 数据随机dp水过
0表示他是作为比较小的那个点 1则相反
技术分享
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int M=150007; 
int read(){
    int ans=0,f=1,c=getchar();
    while(c<0||c>9){if(c==-) f=-1; c=getchar();}
    while(c>=0&&c<=9){ans=ans*10+(c-0); c=getchar();}
    return ans*f;
}
int w[M],n,f[M][2]; 
int main()
{
    n=read();
    for(int i=1;i<=n;i++) w[i]=read(),f[i][0]=f[i][1]=1;
    for(int i=1;i<=n;i++)
        for(int j=i-1;j;j--){
            if(w[i]>w[j]) f[i][1]=max(f[i][1],f[j][0]+1);
            if(w[j]>w[i]) f[i][0]=max(f[i][0],f[j][1]+1);
            if(f[i][0]!=1&&f[i][1]!=1) break;
        }
    printf("%d\n",max(f[n][0],f[n][1]));
    return 0;
}
View Code

T6 华容道 题目传送门

 这道题黄学长都弃坑了 我纠结什么呢 以后补吧 hzwer

 

noip2013 提高组