2018-2019 ACM-ICPC, Asia Shenyang Regional Contest 一些题解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lingzidong/article/details/84726702

J How Much Memory Your Code Is Using?
直接模拟,比较简单。
G. Best ACMer Solves the Hardest Problem
赛后参考了sjf大佬的解法,想了一下的确是自己SB了……
首先题目中要求的是正好等于sqrt(k)的点,可想而知这些点真的不多。
我们先处理出来 a 2 + b 2 = c 2 a^2+b^2=c^2 每个c存一组a,b。
之后我们操作3,4,也就是要找 ( x x 0 ) 2 + ( y y 0 ) 2 = k 2 (x-x_0)^2 + (y-y_0)^2=k^2 也就是说我现在知道每个x-x0的绝对值是什么,有几个,算上y的话,1每种绝对值就有种情况,暴力一下就行了。
有个非常重要的优化,我们记录一下添加进去和一开始就有的点,因为只有这些点的值发生了变化,我们就不用每次清空二维数组了。

#include <bits/stdc++.h>
#include <cstring>
#define ll long long
#define next fuck
#define fi first
#define se second
using namespace std;
const int MAXN = 6000;
bool vis[MAXN+10][MAXN+10];
int val[MAXN+10][MAXN+10];
vector<pair<int,int> > f[10000010];
vector<pair<int,int> > tot;
int dx[4] = {1,1,-1,-1};
int dy[4] = {1,-1,-1,1};
int main()
{

    for(int i  =0;i<=MAXN;i++)
    {
        for(int j = 0;j<=MAXN;j++)
        {
            if(i*i+j*j<=10000000) f[i*i+j*j].emplace_back(i,j);
            else break;

        }
    }
    int ca,cat = 1;
    scanf("%d",&ca);
    while(ca--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        tot.clear();
        int op,x,y,w,k;

        ll last = 0,ans = 0;
        for(int i = 0;i<n;i++)
        {
            scanf("%d%d%d",&x,&y,&w);
            vis[x][y] = 1;
            val[x][y] = w;
            tot.push_back(make_pair(x,y));
        }
        printf("Case #%d:\n",cat++);
        auto check = [&](int x,int y)
        {
            return x >= 1 && x<= MAXN && y >= 1 && y <= MAXN && vis[x][y] == 1;
        };
        set<pair<int,int> > s;
        while(m--)
        {

            s.clear();
            scanf("%d%d%d",&op,&x,&y);
            x = (x + last) % 6000 + 1;
            y = (y + last) % 6000 + 1;
           // cout<<x<<' '<<y<<endl;
            if(op == 1)
            {
                scanf("%d",&w);
                vis[x][y] = 1;
                val[x][y] = w;
                tot.push_back(make_pair(x,y));
            }
            else if(op == 2)
            {
                vis[x][y] = 0;
                val[x][y] = 0;
            }
            else if(op == 3)
            {
                scanf("%d%d",&k,&w);
                for(auto &it : f[k])
                {
                    for(int i = 0;i<4;i++)
                    {
                        int xx = x - it.fi*dx[i];
                        int yy = y - it.se*dy[i];
                        if(check(xx,yy)) s.insert(make_pair(xx,yy));
                    }
                }
                for(auto &it : s) val[it.fi][it.se] += w;
            }
            else
            {
                scanf("%d",&k);
                last = 0;
                for(auto it : f[k])
                {
                    for(int i = 0;i<4;i++)
                    {
                        int xx = x - it.fi*dx[i];
                        int yy = y - it.se*dy[i];
                        if(check(xx,yy)) s.insert(make_pair(xx,yy));
                    }
                }
                for(auto &it : s) last += val[it.fi][it.se];
                printf("%lld\n",last);
                //last = ans;
            }
        }
        for(auto it : tot)
        {
            vis[it.fi][it.se] = val[it.fi][it.se] = 0;
        }
    }
    return 0;
}

C. Insertion Sort
正解好像不是找规律呢
打个表,发现每个答案可以写成 a + i = 1 n k + 1 b i , b n = b 1 + n d a+\sum_{i=1}^{n-k+1} b_i,b_n=b_1+nd 的样子,分析一下nk只有50,不用求逆元来求等差数列了。
注意如果 n<=k 就直接是n!

#include <bits/stdc++.h>
#define ll long long
using namespace std;
int main()
{
    int ca,cat = 1;
    scanf("%d",&ca);
    while(ca--)
    {
        ll n,k,mod;
        scanf("%lld%lld%lld",&n,&k,&mod);
        ll nk = 1LL;
        ll mk = 1LL;
        if(k > n) k = n;
        for(ll i = 2LL;i<=k;i++)
        {
            nk = (nk *i) % mod;
        }
        for(ll i = 2LL;i<=k-1;i++)
        {
            mk = (mk*i) % mod;
        }
        ll kk = k*k % mod;
        ll b1 = kk*mk % mod;
        ll d1 = 2LL*nk%mod;
        ll sumb = 0,bi = b1;
        for(int i = 0;i<=n-k-1;i++)
        {
            //cout<<bi<<endl;
            sumb = (sumb + bi) % mod;
            bi = (bi + d1) % mod;
        }
        //cout<<nk<<' '<<sumb<<endl;
        ll ans = nk + sumb % mod;
        if(n == k)
        {
            printf("Case #%d: %lld\n",cat++,nk%mod);
        }
        else printf("Case #%d: %lld\n",cat++,ans%mod);

    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/lingzidong/article/details/84726702