2018杭电多校第四场

B

见面就想暴力,然后数据量直接劝退

题解说是莫队,确实,只要可以推出由S(i,j) 可以转移到 S(i,j+1),S(i,j-1),S(i-1,j),S(i+1,j),就符合用莫队的条件了

ps:顺便存一下组合数的模板,以前本弱竟然连这个都没存

#include 
using namespace std;

typedef long long ll;
const int N = 100100;
const int mod = 1000000007;
struct Node {
    int l, r;
    int Index;
};
int sq;
bool operator<(const Node &a, const Node &b) {
    return a.r / sq == b.r / sq? a.l < b.l: a.r < b.r;
}
int T, n, m, l, r, Max;
int ans[N];
Node node[N];
int inv[N], pro[N], invpro[N];
void Init() {
    inv[1] = 1;
    for(int i = 2; i < N; ++i) {
        inv[i] = (ll)(mod - mod / i) * inv[mod % i] % mod;
    }
    pro[0] = invpro[0] = 1;
    for(int i = 1; i < N; ++i) {
        pro[i] = (ll)pro[i - 1] * i % mod;
        invpro[i] = (ll)invpro[i - 1] * inv[i] % mod;
    }
}
int get_C(int n, int m) {
    if(n < m) {
        return 0;
    }
    return (ll)pro[n] * invpro[m] % mod * invpro[n - m] % mod;
}
int main() {
    Max = 0;
    Init();
    scanf("%d", &T);
    for(int i = 0; i < T; ++i) {
        scanf("%d%d", &node[i].r, &node[i].l);
        node[i].Index = i;
        Max = max(Max, node[i].r);
    }
    sq = sqrt(Max);
    sort(node, node + T);
    l = 1;
    r = 0;
    ll tmp = 1;
    ll ttmp;
    for(int i = 0; i < T; ++i) {
        while(r < node[i].r) {
            ttmp = tmp + tmp;
            if(ttmp >= mod) {
                ttmp -= mod;
            }
            tmp = ttmp - get_C(r, l);
            if(tmp < 0) {
                tmp += mod;
            }
            ++r;
        }
        while(l > node[i].l) {
            tmp = tmp - get_C(r, l);
            if(tmp < 0) {
                tmp += mod;
            }
            --l;
        }
        while(r > node[i].r) {
            ttmp = tmp + get_C(r - 1, l);
            if(ttmp >= mod) {
                ttmp -= mod;
            }
            tmp = (ttmp * inv[2]) % mod;
            --r;
        }
        while(l < node[i].l) {
            tmp = tmp + get_C(r, l + 1);
            if(tmp >= mod) {
                tmp -= mod;
            }
            ++l;
        }
        ans[node[i].Index] = tmp;
    }
    for(int i = 0; i < T; ++i) {
        printf("%d\n", ans[i]);
    }
    return 0;
}

 

E

遇事不决先打表,然后就可以发现它是以2L为循环节的,然后就是二维前缀和的一些操作

#include 
using namespace std;

typedef long long ll;
const int N = 100 + 100;
int T, n, q;
int a[N];
ll num[N][N];
ll Sum(int x, int y) {
    if(x < 0 || y < 0) {
        return 0;
    }
    int nn = n << 1;
    ll ret = num[nn - 1][nn - 1] * ((x + 1) / nn) * ((y + 1) / nn);
    int xx = x % nn;
    int yy = y % nn;
    if(xx != nn - 1) {
        ret += num[xx][nn - 1] * ((y + 1) / nn);
    }
    if(yy != nn - 1) {
        ret += num[nn - 1][yy] * ((x + 1) / nn);
    }
    if(xx != nn - 1 && yy != nn - 1) {
        ret += num[xx][yy];
    }
    return ret;
}
int main() {
    scanf("%d", &T);
    while(T--) {
        scanf("%d", &n);
        for(int i = 0; i < n; ++i) {
            scanf("%d", &a[i]);
        }
        int Index = 0;
        for(int i = 0; i < N; ++i) {
            for(int j = 0; j <= i; ++j) {
                num[j][i - j] = a[Index];
                Index = (Index + 1) % n;
            }
        }
        for(int i = 0; i < N; ++i) {
            for(int j = 0; j < N; ++j) {
                if(i != 0) {
                    num[i][j] += num[i - 1][j];
                }
                if(j != 0) {
                    num[i][j] += num[i][j - 1];
                }
                if(i != 0 && j != 0) {
                    num[i][j] -= num[i - 1][j - 1];
                }
            }
        }
        scanf("%d", &q);
        int x1, x2, y1, y2;
        while(q--) {
            scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
            ll ans = Sum(x2, y2) + Sum(x1 - 1, y1 - 1);
            ans -= Sum(x2, y1 - 1) + Sum(x1 - 1, y2);
            printf("%I64d\n",  ans);
        }
    }
    return 0;
}

 

J

耿直的搜索,先增加列标,列标到最值后增大行标列标归零

#include
#include 
#include 
#include 
#include  
#include   
#include   
#include   
#include   
#include    
#include      
#include      
using namespace std;
 
char s[16][16],w[16][16];
int Ans;
 
void Rot(int a,int b)
{
    for(int i=0;i<4;i++)
        for(int j=0;j<4;j++)
            w[j][3-i]=s[a+i][b+j];
    for(int i=0;i<4;i++)
        for(int j=0;j<4;j++)
            s[a+i][b+j]=w[i][j];
}
 
int tot,vis[16];
 
bool check(int a,int b)
{
    for(int i=a;i=Ans)
        return;
    if(j==4)
        return dfs(i+1,0,k);
    for(int t=0;t<4;t++)
    {
        if(check(i*4,j*4))
            dfs(i,j+1,k+t);
        Rot(i*4,j*4);
    }
}
 
void solve()
{
    for(int i=0;i<16;i++)
        scanf(" %s",s[i]);
    for(int i=0;i<16;i++)
        for(int j=0;j<16;j++)
            if(s[i][j]<='9')
                s[i][j]-='0';
            else
                s[i][j]=s[i][j]-'A'+10;
    Ans=1000;dfs(0,0,0);
    cout<>t;
    while(t--)
        solve();
    return 0;
}

 

K

这一场真是考验代码能力的一场,咕咕咕

#include
#include 
#include 
#include 
#include  
#include   
#include   
#include   
#include   
#include    
#include      
#include      
using namespace std;

char s[1005];
int n;

bool check()
{
    for(int i=1;i='0'&&s[i-1]<='9')&&(s[i+1]>='0'&&s[i+1]<='9'))
            return 0;
    if(s[1]=='+'||s[1]=='*'||s[n]=='+'||s[n]=='*')
        return 0;
    return 1;
}

void solve()
{
    scanf(" %s",s+1);n=strlen(s+1);
    for(int i=1;i<=n;i++)
        if(s[i]=='0'&&!(s[i-1]>='0'&&s[i-1]<='9')&&s[i+1]=='?')
            s[i+1]='+';
        else if(s[i]=='?')
            s[i]='1';
    if(check())
        puts(s+1);
    else
        puts("IMPOSSIBLE");
}

int main()
{
    int t;cin>>t;
    while(t--)
        solve();
    return 0;
}

 

你可能感兴趣的:(2018杭电多校第四场)