2016-11-15 考试总结

又是一天的考试,又是一天的爆0。

Day 2

T1 Calc

一道数学竞赛题,非常的神奇。主要是要把题目所求转化为组合计数。
原题的公式是
nk1=0nk2=0nkm=0m1j=1(kj+1kj)

可以得到公式
ANS=nk=0mk=mn+11m1

最后用费马小定理与逆元完成计算。

#include<bits/stdc++.h>
#define mod 1000000007
using namespace std;
long long sum=1;

void ksm(long long a,long long b)
{
    if(b==1)
    {
        sum=(sum*a)%mod;
        return;
    }
    if(b%2==1)
        sum=(sum*a)%mod;
    a=(a*a)%mod;
    b=b/2;
    ksm(a,b);
}

int main()
{
    int n,m;
    cin>>n>>m;
    ksm(m,n+1);
    long long sum1=sum-1;
    sum=1;
    ksm(m-1,mod-2);
    cout<<(long long)((sum1)*(sum))%mod;
}

T2 Chess

是全卷最难的一道题,因为每一个车会控制一行和一列,所以将列和行分开计算。
使用两个map进行维护。
时间复杂度 O(nlogn2)

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <map>
#include <cctype>
using namespace std;
int n,k,q;
long long Sol;
map<int,int> RCnt,CCnt;
map<int,int> RXor,CXor;
map<pair<int,int>,int> Rook;

void MoveRook(int r,int c,int Val) {
    int Rxor=RXor[r],Cxor=CXor[c];
    Sol-=n-RCnt[Cxor];
    Sol-=n-CCnt[Rxor];
    --RCnt[Rxor];
    Rxor=RXor[r]^=Val;
    ++RCnt[Rxor];
    --CCnt[Cxor];
    Cxor=CXor[c]^=Val;
    ++CCnt[Cxor];
    Sol+=n-CCnt[Rxor];
    Sol+=n-RCnt[Cxor];
    Rook[pair<int,int>(r,c)]^=Val;
}

void Init() {
    cin>>n>>k>>q;
    RCnt[0]=CCnt[0]=n;
    for(int i=0;i^k;++i) {
        int r,c,Val;
        cin>>r>>c>>Val;
        --r;
        --c;
        MoveRook(r,c,Val);
    }
}

void Solve() {
    while(q--) {
        int r1,c1,r2,c2;
        cin>>r1>>c1>>r2>>c2;
        --r1;
        --c1;
        --r2;
        --c2;
        int RookVal=Rook[pair<int,int>(r1,c1)];
        MoveRook(r1,c1,RookVal);
        MoveRook(r2,c2,RookVal);
        cout<<Sol<<endl;
    }
}

int main() {
    Init();
    Solve();
    return 0;
}

T3 Function

因为一个数被取模最多 logx2 次,所以关键便是找到下一次被mod的位置即可。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<iostream>
#include<cctype>

using namespace std;

int l,r,now,pl,n,m;
int num[100010];

struct node
{
    int min;
}tree[400010];

inline void R(int &v)
{
    char c=0;
    v=0;
    while(!isdigit(c))
        c=getchar();
    while(isdigit(c))
    {
        v=(v<<3)+(v<<1)+(c^'0');
        c=getchar();
    }
}

void updata(int k)
{
    tree[k].min=min(tree[k<<1].min,tree[k<<1|1].min);
}

void read()
{
    R(n);
    for(int i=1;i<=n;++i)
        R(num[i]);
}

void build(int k,int s,int t)
{
    if(s==t)
    {
        tree[k].min=num[s];
        return ;
    }
    int mid=(s+t)>>1;
    build(k<<1,s,mid);
    build(k<<1|1,mid+1,t);
    updata(k);
}

void query(int k,int s,int t,int l,int r)
{
    if(tree[k].min>now)
        return ;
    if(pl<=r)
        return ;
    if(l<=s&&t<=r)
    {
        if(s==t)
        {
            pl=s;
            return ;
        } 
        int mid=(s+t)>>1;
        query(k<<1,s,mid,l,r);
        query(k<<1|1,mid+1,t,l,r);
    }
    int mid=(s+t)>>1;
    if(l<=mid)
        query(k<<1,s,mid,l,r);
    if(r>mid)
        query(k<<1|1,mid+1,t,l,r);
}

int main()
{
    read();
    build(1,1,n);
    R(m);
    while(m--)
    {
        R(l);
        R(r);
        now=num[l];
        l++;
        while(now&&l<=r)
        {
            pl=n+1;
            query(1,1,n,l,r);
            if(pl>r)
                break;
            now%=num[pl];
            l=pl+1;
        }
        cout<<now<<'\n';
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值