码迷,mamicode.com
首页 > 其他好文 > 详细

20160917NOIP模拟赛?(?>?<?)?

时间:2017-09-19 14:55:13      阅读:197      评论:0      收藏:0      [点我收藏+]

标签:hup   efi   sqrt   合数   case   break   好的   拼接   math   

T1:寻找(find)

【题目描述】

       你有一个长度为n个由abc三个字母组成的字符串s,你现在想知道有多少三元组(i,j,k)满足:

1、 s[i]=’a’,s[j]=’b’,s[k]=’c’

2、 j^2=ik

请你求出满足条件的三元组的数量

【输入描述】

第一行为n,表示字符串长度

第二行为一个长度为n的字符串。

【输出描述】

       输出一个数, 表示满足条件的三元组的数量。

【样例】

输入

输出

5

abccc

1

【数据范围】

对于30%的数据,

对于50%的数据,

对于70%的数据,

对于100%的数据,

solution:暴力只要判断j^2=i*kj是否为整数就行了,这里附上暴力代码

#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std;
bool check(int m)
{
    double n;
    n=sqrt(m);
    int k=(int)n;
    if(k*k==m) return true;
    else return false;
}
int main()
{
    //freopen("find.in","r",stdin);
    //freopen("find.out","w",stdout);
    char c[5002];
    int j,n,sum=0;
    scanf("%d",&n);
    scanf("%s",c+1);
    for(int i=1;i<=n;i++)
    for(int k=1;k<=n;k++)
    {
        if(check(i*k))
        {
             j=sqrt(i*k);
             if(c[i]==a&&c[j]==b&&c[k]==c)
            //printf("%d %d %d\n",i,j,k);
             sum++;
        }
    }    
    printf("%d\n",sum);
}

 

T2:大芳的逆行板载(boat)

【题目描述】

       大芳有一个不太好的习惯:在车里养青蛙。青蛙在一个n厘米(11n毫米s)的Van♂杆子上跳来跳去。她时常盯着青蛙看,以至于突然逆行不得不开始躲交叉弹。有一天他突发奇想,在杆子上每1厘米为一个单位,瞎涂上了墨水,并且使用mOgic,使青蛙跳过之处墨水浓度增加x。当然,他还会闲着无聊滴几滴墨水再涂♂抹均匀。

他现在无时无刻都想知道,第l厘米到第r厘米墨水的浓度是多少?

哦不!等等,他现在找到了一个计算器,可以输入几个数字与x,计算他们的x次幂和,所以……他想知道的是第l厘米到第r厘米墨水的浓度的x次幂和是多少?

 

大芳有3种舰长技能骚操作:

1、续:把青蛙放到第l厘米处,戳青蛙使其跳至r。效果:第l厘米至第r厘米墨水浓度增加x

2、抚♂摸:擦干杆子某一部分,重新滴加墨水并抹匀。效果:使第l厘米至第r厘米墨水浓度都变成x

最后一种是:

3、压线逆行,将车流看做⑨弹幕找安定点,掏出计算器,大喊板载后计算:

第l厘米至第r厘米墨水浓度的x次幂和是几何?记得答案要模1000000007

【输入描述】

       第一行n和m,表示杆子长n厘米,大芳要进行m次骚操作。

第二行n个数字,表示初始墨水浓度。第i个数字为第i厘米墨水浓度

接下来每行4个数字,依次为:操作编号(1、2或3)l,r,x

【输出描述】

       每次进行3操作,输出一行表示答案

记得模1000000007

【样例】

输入

输出

5 5

19844 14611 26475 4488 6967

2 1 3 15627

2 1 2 30113

2 3 5 14686

2 5 5 32623

3 1 2 8

466266421

【数据范围】

k表示询问的幂的大小,也就是操作3对应的x。

对于20%的数据,满足

对于另外20%的数据,满足

对于另外20%的数据,满足

对于另外20%的数据,满足

对于100%的数据,满足

操作1,2对应的

solution:模拟可以20分,正解是采用线段树。(20万岁( ̄▽ ̄)/)

#include <bits/stdc++.h>
#define ll long long
#define MOD 1000000007
using namespace std;
    int n,m,opt,A,B,C;
    int cnt[11][11];
struct node
{
    ll v[11];
    ll tagt,tagn;
    void init(int x)
    {
        v[0]=1;
        for (int i=1;i<=10;i++)
            v[i]=v[i-1]*x%MOD;
    }
    void add(int x)
    {
        int tv,r;
        for (int i=10;i>=0;i--)
        {
            tv=0,r=1;
            for (int j=i;j>=0;j--)
            {
                tv=(v[j]*cnt[i][j]%MOD*r+tv)%MOD;
                r=(ll)r*x%MOD;
            }
            v[i]=tv;
        }
    }
}tr[400005];
inline int read()
{
    int x=0;char ch=getchar();
    while(ch<0||ch>9)ch=getchar();
    while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();}
    return x;
}
inline int DEC(int x)
{
    return x>=MOD?x-MOD:x;
}
void pushup(int x)
{
    int ls=x<<1,rs=x<<1|1;
    for (int i=0;i<=10;i++)
        tr[x].v[i]=DEC(tr[ls].v[i]+tr[rs].v[i]);
}
void downpush(int k,int l,int r)
{
    int ls=k<<1,rs=k<<1|1,mid=(l+r)>>1;
    if (tr[k].tagt==1)
    {
        if (!tr[ls].tagt) tr[ls].tagt=1;if (!tr[rs].tagt) tr[rs].tagt=1;
        tr[ls].tagn+=tr[k].tagn,tr[rs].tagn+=tr[k].tagn;
        tr[ls].add(tr[k].tagn),tr[rs].add(tr[k].tagn);
    }
    else if (tr[k].tagt==2)
    {
        tr[ls].tagt=tr[rs].tagt=2;
        tr[ls].tagn=tr[rs].tagn=tr[k].tagn;
        tr[ls].init(tr[k].tagn);tr[rs].init(tr[k].tagn);
        for (int i=0;i<=10;i++)
            tr[ls].v[i]=tr[ls].v[i]*(mid-l+1)%MOD,tr[rs].v[i]=tr[rs].v[i]*(r-mid)%MOD;
    }
    tr[k].tagt=tr[k].tagn=0;
}
void build(int k,int l,int r)
{
    if (l==r)
    {
        tr[k].init(read());
        return;
    }
    int mid=(l+r)>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r);
    pushup(k);
}
void update_add(int k,int l,int r,int a,int b,int x)
{
    if (a<=l&&r<=b)
    {
        if (!tr[k].tagt) tr[k].tagt=1;
        tr[k].tagn+=x;
        tr[k].add(x);
        return;
    }
    if (tr[k].tagt) downpush(k,l,r);
    int mid=(l+r)>>1;
    if (a<=mid) update_add(k<<1,l,mid,a,b,x);
    if (mid<b) update_add(k<<1|1,mid+1,r,a,b,x);
    pushup(k);
}
void update_mod(int k,int l,int r,int a,int b,int x)
{
    if (a<=l&&r<=b)
    {
        tr[k].tagt=2;
        tr[k].tagn=x;
        tr[k].init(x);
        for (int i=0;i<=10;i++)
            tr[k].v[i]=tr[k].v[i]*(r-l+1)%MOD;
        return;
    }
    if (tr[k].tagt) downpush(k,l,r);
    int mid=(l+r)>>1;
    if (a<=mid) update_mod(k<<1,l,mid,a,b,x);
    if (mid<b) update_mod(k<<1|1,mid+1,r,a,b,x);
    pushup(k);
}
int query(int k,int l,int r,int a,int b,int x)
{
    if (r<a||l>b) return 0;
    if (a<=l&&r<=b) return tr[k].v[x];
    if (tr[k].tagt) downpush(k,l,r);
    int mid=(l+r)>>1;
    return DEC(query(k<<1,l,mid,a,b,x)+query(k<<1|1,mid+1,r,a,b,x));
}
int main()
{
    freopen("boat.in","r",stdin);
    freopen("boat.out","w",stdout);
    cnt[0][0]=1;
    for (int i=1;i<=10;i++)
    {
        cnt[i][0]=1;
        for (int j=1;j<=i;j++) cnt[i][j]=cnt[i-1][j-1]+cnt[i-1][j];
    }
    n=read(),m=read();
    build(1,1,n);
    for (int i=1;i<=m;i++)
    {
        opt=read(),A=read(),B=read(),C=read();
        switch (opt)
        {
            case 1:
                update_add(1,1,n,A,B,C);
                break;
            case 2:
                update_mod(1,1,n,A,B,C);
                break;
            case 3:
                printf("%d\n",query(1,1,n,A,B,C));
                break;
        }
    }
    return 0;
}

T3:消消乐(tet)

【题目描述】

       有一个2n个数字排成一列,这个数列中由1..n中的数字组成,每个数字都恰好出现两次。每个回合可以交换相邻两个数字,交换以后如果有两个相同的数字相邻,那么将这两个数字消除,并将这两个数字的两端拼起来;如果拼接后的数列仍有相同的数字相邻,那么将引发连锁反应直到没有两个相同数字相邻。现在你想知道最少需要几个回合可以消除所有的数字。

【输入描述】

       第一行输入一个n,表示数字范围。

       接下来的2n行,每行一个数字,表示第i个位置的数字。

【输出描述】

       第一行输出一个数,表示最少需要的回合数w。

       接下来的w行,每行输出一个数m[i]。m[i]表示对于第i回合,你的操作为交换当前数列中的第m[i]个数和第(m[i]+1)个数。如果有多种方案,允许输出任意一种。

保证存在不超过的答案。

【样例】

输入

输出

5

5

2

3

1

4

1

4

3

5

2

2

5

2

【数据范围】

       对于30%的数据,

       对于100%的数据,

 

#include<cstdio>
#define For( i , _Begin , _End ) for( int i = (_Begin) , i##END = (_End) ; i <= (i##END) ; i++ )
template< typename type >inline void swap( type &x , type &y ){ type t = x ; x = y ; y = t ; }
template< typename type >inline void scanf( type &In ){
    In = 0;char ch = getchar();type f = 1;
    for( ;ch> 9||ch< 0;ch = getchar() )if( ch == - ) f = -1;
    for( ;ch>=0&&ch<=9;ch = getchar() )In = In * 10 + ch - 0;In *= f;
}
static const int maxn = 5e4 + 10;
static const int maxm = 1e6 + 10;
int n,size,tp;
int ans[maxm],pos[maxn],stk[maxm];
int main(){
    freopen("tet.in","r",stdin);
    freopen("tet.out","w",stdout); 
    scanf( n ) ;
    For( i , 1 , n << 1 ){
        int x ;
        scanf( x ) ;
        stk[ ++tp ] = x;
        if( pos[x] ){
            if( pos[x] == tp - 1 ){ tp -= 2 ; continue ; }
            int t = pos[x] ;
            while( t != tp - 1 ){
                swap( stk[t] , stk[t + 1] );
                pos[ stk[t] ]--;
                ans[ ++size ] = t++;
            }
            tp -= 2 ;
            pos[x] = 0 ;
        }
        else pos[x] = tp ;
    }
    printf("%d\n" , size );
    For( i , 1 , size )printf("%d\n" , ans[i] );
    return 0;
}

 

20160917NOIP模拟赛?(?>?<?)?

标签:hup   efi   sqrt   合数   case   break   好的   拼接   math   

原文地址:http://www.cnblogs.com/qizhengquan/p/7550976.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!