学习笔记(6)

来源:互联网 发布:单片机开发板套件 编辑:程序博客网 时间:2024/04/29 03:47

  这两天做的CF,突然发现数学知识真的是不够用了,别人一下想出来的东西,我想了半天,又是查题解,又是问TG的,最后才明白,还是太弱了啊,贴下我纠结好久的题,算是数学题吧...

Hacking Cypher

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<string>
#include<set>
#include<algorithm>
#include<cmath>


#define ll __int64
#define MAX 1000009
using namespace std;


int vis[MAX];


int main()
{
    string b,xx,yy;
    ll x,y,i;
    cin>>b;
    cin>>x>>y;
    int flag = 0;
    int len = b.size();
    int k = 0;
    for(i=0; i<len; i++)
    {
        k = k*10+b[i]-'0';
        if(k%x==0)
        {
            vis[i+1]++;
        }
        k%=x;
    }
    int l =1;
    int t = 0;
    for(i=len-1; i>=0; i--)
    {
        t = l*(b[i]-'0')%y+t%y;
        if(t%y==0)
        {
            vis[i]++;
        }
        l = (l*10)%y;
    }
    for(int i=0; i<len; i++)
        if(vis[i]==2 && b[i]-48!=0)
        {
            printf("YES\n");
            for(int j=0; j<i; j++)
                printf("%c",(int)b[j]);
            printf("\n");
            for(int j=i; j<len; j++)
                printf("%c",b[j]);
            printf("\n");
            return 0;
        }
    printf("NO\n");


}
/*
思路:从左到右求出在每一位对x的余数求出之后 在判断余数是否对x取余是否为零,如果为零,标记位置;
      从右到左求出在每一位对y的余数求出之后 在判断余数是否对y取余是否为零,如果为零,标记位置;
      如果vis[i]==2&&b[i]-'0'!=0,输出答案
*/

==

就是这么弱,TG都AK的题····我才A了三个,还有两个是赛后A的,唉,还要好好学啊,今天接着学习线段树,应该是单点更新的最后一题了,说道线段树,昨天求了最小逆序数,当然了,是照傻崽敲得...

#include<cstdio>#include<algorithm>#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1using namespace std;const int MAXN = 55555;int sum[MAXN<<2];void PushUP(int rt){    sum[rt] = sum[rt<<1] + sum[rt<<1|1];}void build(int l,int r,int rt){    sum[rt] = 0;    if(l == r )    {        return ;    }    int m =(r+l)>>1;    build(lson);    build(rson);    PushUP(rt);}void update(int p,int l,int r,int rt){    if(l == r)    {        sum[rt]++;        return ;    }    int m = (r+l)>>1;    if(p<=m)        update(p,lson);    else        update(p,rson);    PushUP(rt);}int query(int L,int R,int l,int r,int rt){    if(L<=l&&r<=R)    {        return sum[rt];    }    int m =(l+r)>>1;    int ret = 0;    if(L<=m)        ret+=query(L,R,lson);    if(R>m)        ret+=query(L,R,rson);    return ret;}int x[MAXN];int main(){    int n,sum,i;    while(~scanf("%d",&n))    {        build(0,n-1,1);        sum = 0;        for(i=0;i<n;i++)        {            scanf("%d",&x[i]);            sum += query(x[i],n-1,0,n-1,1);            update(x[i],0,n-1,1);        }        int ret = sum;        for(i = 0;i<n;i++)        {            sum+=n-2*x[i]-1;            ret = min(sum,ret);        }        printf("%d\n",ret);    }}
这里有两点说明,逆序数的比较大小实际上就是存储顺序,先存入的自加1,然后区间求和,这个和,也就是逆序对的个数,还有个规律,就是每当第一个数放到最后是,逆序数减少a[i]个,增加n-a[i]-1个



0 0
原创粉丝点击