2014多校联合-第五场

1001:Inversion

模版题,求逆序数对。有多少逆序数对,就可以剪掉多少。

1003:Least common multiple

对于每一个子集,lcm为2的a的最大值次方*3的b的最大值次方。

所以我们只需要求出以某个b为b的最大值的时候,a的最大值的分布情况即可。

我们先把b从小到大排序。

对于某一个b,我门只需要求出之前出现过的a比当前a小的数量为x;

那么就可知对于这些a的子集,为2^x个,并且,每个子集a的最大值都为当前a。

我么还需要求出对于大于当前a的a有多少个比a小的数,我们可以用线段树逐步维护。

#include <iostream>
#include<stdio.h>
#include<vector>
#include<queue>
#include<stack>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<map>
using namespace std;
#define LL long long
#define lcm(a,b) (a*b/gcd(a,b))
#define maxn 110000
#define lson l,(l+r)/2,rt<<1
#define rson (l+r)/2+1,r,rt<<1|1
struct list
{
    int a,b;
    friend bool operator <(const list &a,const list &b)
    {
        return a.b<b.b;
    }
}p[maxn];
int cmp(list a,list b)
{
    return a.a<b.a;
}
int ed[maxn];
LL num[maxn<<2];
LL sum[maxn<<2];
LL lazy[maxn<<2];
void push_down(int rt)
{
    if(lazy[rt]!=1)
    {
        sum[rt<<1]*=lazy[rt];
        sum[rt<<1|1]*=lazy[rt];
        sum[rt<<1]%=mod;
        sum[rt<<1|1]%=mod;
        lazy[rt<<1]*=lazy[rt];
        lazy[rt<<1|1]*=lazy[rt];
        lazy[rt<<1]%=mod;
        lazy[rt<<1|1]%=mod;
        lazy[rt]=1;
    }
}
void push_up(int rt)
{
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
    num[rt]=num[rt<<1]+num[rt<<1|1];
    sum[rt]%=mod;
}
void creat(int l,int r,int rt)
{
    num[rt]=sum[rt]=0;
    lazy[rt]=1;
    if(l!=r)
    {
        creat(lson);
        creat(rson);
        return;
    }
}
void insert(int x,int l,int r,int rt)
{
    if(x<l||x>r)return;
    if(l==r&&l==x)
    {
        num[rt]++;
        sum[rt]=M.q_mod(2,ed[x],mod);
        sum[rt]=(sum[rt]*lazy[rt])%mod;
        return;
    }
    push_down(rt);
    insert(x,lson);
    insert(x,rson);
    push_up(rt);
}
void updata(int ll,int rr,int l,int r,int rt)
{
    if(ll>rr)return ;
    if(ll>r||rr<l)return;
    if(ll<=l&&rr>=r)
    {
        lazy[rt]*=2;
        sum[rt]=sum[rt]*2%mod;
        return;
    }
    push_down(rt);
    updata(ll,rr,lson);
    updata(ll,rr,rson);
    push_up(rt);
}
LL query(int ll,int rr,int leap,int l,int r,int rt)
{
    if(ll>rr)return 0;
    if(ll>r||rr<l)return 0;
    if(ll<=l&&rr>=r)
    {
        if(leap==0)return num[rt];
        else return sum[rt];
    }
    push_down(rt);
    return query(ll,rr,leap,lson)+query(ll,rr,leap,rson);
}
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&p[i].a,&p[i].b);
        }
        sort(p+1,p+n+1,cmp);
        for(int i=1;i<=n;i++)
        {
            ed[i]=p[i].a;
            p[i].a=i;
        }
        creat(1,n,1);
        sort(p+1,p+n+1);
        LL sum=0;
        for(int i=1;i<=n;i++)
        {
            int k=p[i].a;
            LL x=query(1,k-1,0,1,n,1);
            LL y=query(k+1,n,1,1,n,1);
            LL now=M.q_mod(3,p[i].b,mod);
            LL ps=((M.q_mod(2,ed[k],mod))*(M.q_mod(2,x,mod)))%mod;
            sum+=now*((ps+y)%mod)%mod;
            insert(k,1,n,1);
            updata(k+1,n,1,n,1);
            sum=sum%mod;
        }
        cout<<sum<<endl;
    }
    return 0;
}

1005:Parenthese sequence

我的做法好像不是正经做法。。。sad

首先对于每一个)进行匹配(,如果匹配不到(,就匹配最前面的?,如果无法匹配,那就肯定无解。

一遍匹配之后,还剩下(还有?。

把每一个剩下的(匹配最后面的?;如果匹配不到?,肯定无解。

假如现在剩下x个?;

如果x是奇数,肯定无解。

如果x为0,肯定唯一解。

如果x>2,肯定多解。

如果x=2,那就把第一个?置为),第二个?置为(,如果可信,那就多解,否则,唯一解。

#include <iostream>
#include<stdio.h>
#include<vector>
#include<queue>
#include<stack>
#include<string.h>
#include<algorithm>
#include<map>
using namespace std;
#define LL long long
#define gcd(a,b) (b==0?a:gcd(b,a%b))
#define lcm(a,b) (a*b/gcd(a,b))
int pre[1100000];
int next[1100000];
char str[1100000];
stack<int>st;
stack<int>we;
int biao[1100000];
int fbiao[1100000];
int main()
{
    while(~scanf("%s",str))
    {
        while(!st.empty())st.pop();
        while(!we.empty())we.pop();
        memset(pre,-1,sizeof(pre));
        memset(next,-1,sizeof(next));
        int len=strlen(str);
        int last=-1;
        int leap=0;
        int sts=-1;
        for(int i=0;i<len;i++)
        {
            if(str[i]=='(')
            {
                st.push(i);
            }
            else if(str[i]==')')
            {
                if(st.empty())
                {
                    leap=1;
                    if(sts==-1)
                    {
                        leap=-1;
                        break;
                    }
                    else
                    {
                        str[sts]='(';
                        sts=next[sts];
                        if(sts==-1)
                        {
                            pre[sts]=-1;
                            sts=last=-1;
                        }
                        else pre[sts]=-1;
                    }
                }
                else
                {
                    int x=st.top();
                    st.pop();
                }
            }
            else if(str[i]=='?')
            {
                pre[i]=last;
                if(sts==-1)sts=i;
                else next[last]=i;
                last=i;
               // cout<<sts<<endl;
            }
        }
        if(leap==-1)
        {
            cout<<"None"<<endl;
            continue;
        }
        while(!st.empty())
        {
            if(last==-1)
            {
                break;
            }
            int x=st.top();
            if(x<last)
            {
                st.pop();
                str[last]=')';
                last=pre[last];
            }
            else break;
        }
        int ss=0;
        while(last!=-1)
        {
            last=pre[last];
            ss++;
        }
       // cout<<ss<<endl;
        if(leap==-1||!st.empty()||ss%2)
        {
            cout<<"None"<<endl;
            continue;
        }
        if(ss>2)
        {
            cout<<"Many"<<endl;
            continue;
        }
        if(ss==0)
        {
            cout<<"Unique"<<endl;
            continue;
        }
        while(!st.empty())st.pop();
        int lp=0;
        leap=1;
       // cout<<str<<endl;
        for(int i=0;i<len;i++)
        {
            if(str[i]=='?')
            {
                if(lp==0)
                {
                    str[i]=')';
                    lp++;
                }
                else str[i]='(';
            }
        }
     //   cout<<str<<endl;
        int i;
        for(i=0;i<len;i++)
        {
            if(str[i]=='(')st.push(i);
            else if(str[i]==')')
            {
                if(st.empty())break;
                else st.pop();
            }
        }
        if(i<len)cout<<"Unique"<<endl;
        else cout<<"Many"<<endl;
    }
    return 0;
}

1009:Exclusive or

因为结果是一些数的异或和。

我们就可以枚举每一位为1时,是由哪些数异或得来的。

对于当前位,如果A,B异或结果为1,那么A,B这两个数的当前位一个为1,一个为0,共有两种情况。

已知A+B=n。

那么对于当前位之前的数的和可以求出x种情况,对于当前位之后的数的和可以求出有y种情况。

那么总过有x*y*2种情况。

又因为A,B都是非0的,所以还需要减去0的情况。

又因为是大数。。。所以要用java,大数用C++太费劲了。。

import java.util.Scanner;
import java.math.*;

public class Main {
    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        BigInteger n,m,sum,zero,one,two,x,k,y,ta,tb,z;
        BigInteger bit[] = new BigInteger[3300];
        bit[0] = BigInteger.valueOf(1);
        int i;
        for(i = 1;i <= 3000;i ++)
            bit[i] = bit[i-1].multiply(BigInteger.valueOf(2));
        zero = BigInteger.valueOf(0);
        one = BigInteger.valueOf(1);
        two = BigInteger.valueOf(2);
        while(cin.hasNext())
        {
            n = cin.nextBigInteger();
            m = n;
            sum = BigInteger.valueOf(0);
            for(i = 1;;i ++)
            {
                n = m.subtract(bit[i-1]);
                if(n.compareTo(zero) == -1)
                    break;
                x=n.divide(bit[i]).add(one);
                k=n.mod(bit[i]);
                if(bit[i-1].subtract(one).compareTo(k) == -1)
                    ta = bit[i-1].subtract(one);
                else
                    ta = k;
                if(zero.compareTo(k.subtract(bit[i-1]).add(one)) == 1)
                    tb = zero;
                else
                    tb = k.subtract(bit[i-1]).add(one);
                y=ta.subtract(tb).add(one);
                sum = sum.add(x.multiply(y).multiply(two).multiply(bit[i-1]));
                z = m.divide(bit[i]);
                k = m.divide(bit[i-1]);
                z = z.multiply(two);
                if(k.compareTo(z) != 0)
                {
                    sum = sum.subtract(bit[i-1].multiply(two));
                }
            }
            System.out.println(sum);
        }

    }
}

1010:Matrix multiplication

瞎搞题,把所有的0都去掉,然后就可以了。。。

理论时间复杂度为800*800*800*(2/3)*(2/3)

#include <iostream>
#include<stdio.h>
#include<vector>
#include<queue>
#include<stack>
#include<string.h>
#include<algorithm>
#include<map>
using namespace std;
#define LL long long
#define gcd(a,b) (b==0?a:gcd(b,a%b))
#define lcm(a,b) (a*b/gcd(a,b))
//O(n)求素数,1-n的欧拉数
#define N 100010
//A^x = A^(x % Phi(C) + Phi(C)) (mod C)
int a[880][880];
int b[880][880];
int aa[880][880];
int bb[880][880];
int c[880][880];
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        memset(aa,0,sizeof(aa));
        memset(bb,0,sizeof(bb));
        memset(c,0,sizeof(c));
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                scanf("%d",&a[i][j]);
                a[i][j]%=3;
            }
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                scanf("%d",&b[i][j]);
                b[i][j]%=3;
            }
        }
        for(int i=1;i<=n;i++)
        {
            int x=-1;
            for(int j=n;j>=0;j--)
            {
                aa[i][j]=x;
                if(a[i][j])x=j;
            }
        }
        for(int i=1;i<=n;i++)
        {
            int x=-1;
            for(int j=n;j>=0;j--)
            {
                bb[i][j]=x;
                if(b[i][j])x=j;
            }
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=aa[i][0];j!=-1;j=aa[i][j])
            {
                for(int k=bb[j][0];k!=-1;k=bb[j][k])
                    c[i][k]+=a[i][j]*b[j][k];
            }
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                printf("%d",c[i][j]%3);
                if(j!=n)printf(" ");
                else printf("\n");
            }
        }
    }
    return 0;
}

2014多校联合-第五场

时间: 2024-10-01 01:29:02

2014多校联合-第五场的相关文章

HDOJ多校联合第五场

1001 题意:求逆序对,然后交换k次相邻的两个数,使得剩下的逆序对最少. 分析:题目用到的结论是:数组中存在一对逆序对,那么可以通过交换相邻两个数使得逆序对减少1,交换k次,可以最多减少k个. 嘉定ai>aj,i < j,如果ai,aj相邻的,那么显然可以通过交换减少1:不相邻的情况, 考虑ak,k = j-1; #11:ak > aj,那么ak,aj构成逆序对,交换后逆序对减少1: #12:ak<=aj,那么ai,ak构成逆序对,问题转化为更小规模,可以通过同样的方法进一步分析

2014多校联合-第六场

最近这两场好无奈啊... 今天这场最后30分钟敲1001,压力倍增,虽然思路比较明确,但是代码打起来不怎么容易. 但是还是好在25分钟左右debug结束.提交wa,再提交,依然WA.......最后5分钟,还是没有AC掉. 一开始以为是精度问题,后来才sb的发现原来数组开小了. 在压力环境下保证代码的效率和质量真不是一件容易的事情.不过数组开小了,真是不可原谅. 1001:Map 题目相当于几条链表.把链表排成几行. 然后枚举每一列的状态会被操作多少次. 然后把和累加起来,然后直接除以状态总数.

2014多校联合-第七场

1005: ( Stupid Tower Defense ) 由题意我们很明显可以知道,红色的塔放在最后面是最优的. 假如前i个塔,放j个绿塔,i-j个蓝塔.那么无论前i个塔的顺序怎么放,对后面的塔造成的影响是完全相同的. dp[i][j]:前i个塔,放j个绿塔,能获得的最大价值. dp[i][j]=max(dp[i-1][j-1]+当前塔放绿塔获得的能量值,dp[i-1][j]+当前塔放蓝塔获得的能量值): #include <iostream> #include<stdio.h>

2014多校联合-第八场

1001:2048 很明显,一开始看错题了...sad 这题目我感觉挺卡时间的... dp[i][j]:在选择2^i的时候,选择的和为j*2^i到(j+1)*2^i-1时候的情况. #include <iostream> #include<stdio.h> #include<vector> #include<queue> #include<stack> #include<string.h> #include<algorithm&

2014多校联合训练第一场(组队训练)

这是我.potaty.lmz第二次训练,毕竟经验不足,加上水平不够,导致我们各种被碾压. A - Couple doubi: 这道题是道比较水的数论.但我们都没想出来要怎么做.后来是potaty提议打个表看看,然后lmz打出表后发现了规律.我还没细看,待研究后再补全. D - Task: 这道题一看就知道是个贪心(现在只要是有deadline的题我都觉得是贪心了).虽然想出来了,但还是不会严格证明为什么只要取满足task的且y最小(y相等时x最小)的machine就行了. 我的做法是把所有mac

2014多校联合五(HDU 4911 HDU 4915 HDU 4920)

HDU 4911 Inversion 题意:n个数字  通过k次相邻交换  使得逆序对数最少 思路:如果序列为 XXXABYYY  假设A和B位置互换  易知X和AB.Y和AB的逆序对数不变  换句话说一次交换最多使逆序对减少1  那么只需要求原逆序对数和k进行比较即可 代码: #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 100100 type

hdu 4865 Peter&amp;#39;s Hobby(2014 多校联合第一场 E)

Peter's Hobby Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 545    Accepted Submission(s): 237 Problem Description Recently, Peter likes to measure the humidity of leaves. He recorded a leaf

2014多校联合第一场

1001:Couple doubi 暴力打表找规律可知,对于任意的p. (1^i+2^i+...+(p-1)^i)%p={ 非0     ,i%(p-1)==0 0        ,  i%(p-1)!=0 } 所以,结果就很显然了. #include <iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<stdlib.h> #include<c

hdu 4865 Peter&#39;s Hobby(2014 多校联合第一场 E)

题意:已知昨天天气与今天天气状况的概率关系(wePro),和今天天气状态和叶子湿度的概率关系(lePro)第一天为sunny 概率为 0.63,cloudy 概率 0.17,rainny 概率 0.2.给定n天的叶子湿度状态,求这n天最可能的天气情况 分析:概率dp设 dp[i][j] 表示第i天天气为j的最大概率,pre[i][j]表示第i天天气最可能为j的前一天天气,dp[i][j]=max(dp[i-1][k]+log(wePro[k][j])+log(lePro[j][lePos[i]]