2018-ACM-ICPC-沈阳

C. Insertion Sort

题意

假设存在一个数组A,长度为n,包含1到n这些数:[1,2,3,……,n-1,n],但不保证顺序。
输入整数n、k、q。

  • n:数组A的长度。
  • k:在数组A中,能对前k个数排序。
  • q:结果对q求模。
    输出一个整数,表示有多少数组A的排列组合,满足对前k个数排序后,其中有序的数不少于n-1个。

关键词

数论、排列组合、排序

思路

对于输入的k,分几种情况进行讨论:

  1. k=1
    k为1时,就是只能对第一个数排序,并不会影响整个数组的顺序,可以理解成什么用也没有。
    结果为:n*(n-2)+2。
  2. k>=n-1
    此时,无论数组A如何排列,都能满足至少存在n-1个数有序
    结果为:n!。
  3. k∈(1, n-1)
    此时为最普遍的一种情况可以按照排序前的情况,对其继续细分:
    k∈(1, n-1)时的细分情况

结果为:k!+k!*(n-k-1)+k!*(n-k-1)2+k!*k*(n-k)。

代码

#include <bits/stdc++.h>

#define Debug 0
#define MAXN 300056
#define MAXM 200
#define MOD 1000000007
#define INF 0x3f3f3f3f
#define PI 3.1415926535
#define pb push_back
#define SYNC ios::sync_with_stdio(false);
//#define FILE_IN "I:\\acm-workspace\\CLion-Project\\in.txt"
typedef long long ll;
typedef std::pair<int, int> Pair;

using namespace std;
int q;
// Calculate the factorial
ll jc (int x)
{
    ll t = 1;
    for (int i = 2; i <= x; ++i)
    {
        t = (t * i) % q;
    }
    return t;
}


int main ()
{
#ifdef FILE_IN
    freopen(FILE_IN, "r", stdin);
#endif
    SYNC
    int T;
    cin >> T;
    int Case = 0;
    while (T--)
    {
        int n, k;
        cin >> n >> k >> q;
        if (k == 1)
        {
            cout << "Case #" << ++Case << ": " << (n * (n - 2) + 2) % q << endl;
        } else if (k >= n - 1)
        {
            cout << "Case #" << ++Case << ": " << jc(n) << endl;
        } else
        {
            ll m = jc(k);
            ll t = n - k - 1;
            ll ans = 0;
            ans = (ans + m * (t * t + t + 1)) % q;
            ans = (ans + m * k * (n - k)) % q;
//            ans = (ans + (t * t + t + 1) * m + m * n * (n - k)) % q;
            cout << "Case #" << ++Case << ": " << ans << endl;
        }


    }

#ifdef FILE_IN
    fclose(stdin);
#endif

    return 0;
}

G. Best ACMer Solves the Hardest Problem

题意

在一个二维平面中,给定一堆带权值的点,并定义四个操作:

  1. 增加一个点。
  2. 删除一个点。
  3. 给定一个点的坐标x,y和半径k,将到这个点(x,y)距离为k的点,权值增加w。
  4. 给定一个点的坐标x,y和半径k,求到这个点(x,y)距离为k的点的权值之和。

当进行操作4时需要输出结果。

关键词

分解平方和、欧几里得距离、二维坐标系、卡时间

思路

这个题很容易想到暴力的解法:遍历所有点或者遍历长度为6000的坐标系去做,结果一定会Time limit exceeded
值得注意的是:

  1. 对于给定的k,能满足a2+b2=k2的a,b数量是比较少的。
    在预处理中,把k按照a2+b2=k2分解为若干个a、b这样的整数对保存起来。在之后处理到x,y距离为k的点时,直接拿来用,时间上会快很多。
  2. 题目给的坐标系范围在6000以内,可以直接使用数组保存,但是,6000*6000的数组在每个案例中都要初始化,使用memset也会比较耗时间。
    直接将每次输入或插入的点坐标保存起来,每个案例处理完之后,按照保存的坐标将上面的点去掉,这样每次最多也就会将整个数组初始化一次的时间,比直接使用memset快很多。

这两点也是最容易卡时间的点,在这个上面贡献了无数发TLE,只要处理好这2个问题,不用读写挂也不会有太大问题。

代码

#include <bits/stdc++.h>

#define Debug 0
#define MAXN 6010
#define MAXM 200
#define MAXK 10000010
#define MOD 6000
#define INF 0x3f3f3f3f
#define PI 3.1415926535
#define pb push_back
#define SYNC ios::sync_with_stdio(false);
//#define FILE_IN "I:\\acm-workspace\\CLion-Project\\in.txt"
typedef long long ll;
typedef std::pair<int, int> Pair;

using namespace std;

ll G[MAXN][MAXN];

vector<Pair> factors[MAXK];
int n, m;

// Used to restore the manipulated coordinates
vector<Pair> changed;

// Use 'set' to remove the duplicate positions
// Sometimes the same 'tx' and 'ty' will appear multiple times in 'increase' method and 'sum' method
set<Pair> se;
ll last_ans = 0;

int dx[] = {-1, -1, 1, 1};
int dy[] = {-1, 1, 1, -1};

inline bool check (int x, int y)
{ return x > 0 && x <= 6000 && y > 0 && y <= 6000 && G[x][y] > 0; }

inline void init ()
{
    for (int i = 0; i < MAXN; ++i)
    {
        for (int j = 0; j < MAXN; ++j)
        {
            int sq = i * i + j * j;
            if (sq < MAXK)
            {
                factors[sq].pb(Pair(i, j));
            } else
                break;
        }
    }
}

inline void init_xy (int &x, int &y)
{
    x = (x + last_ans) % MOD + 1;
    y = (y + last_ans) % MOD + 1;
}

inline void add (int x, int y, int k, bool ini = 0)
{
    if (ini)
        init_xy(x, y);

    G[x][y] = k;
    changed.pb(Pair(x, y));
}

inline void remove (int x, int y)
{
    init_xy(x, y);
    G[x][y] = 0;
}

inline void increase (int x, int y, int k, int w)
{
    init_xy(x, y);
    se.clear();
    for (auto p : factors[k])
    {
        int tx, ty;
        for (int i = 0; i < 4; ++i)
        {
            tx = x + dx[i] * p.first;
            ty = y + dy[i] * p.second;
            if (check(tx, ty))
            {
                se.insert(Pair(tx, ty));
            }
        }
    }
    for (auto p:se)
    {

        G[p.first][p.second] += w;
    }

}

inline ll sum (int x, int y, int k)
{
    init_xy(x, y);
    ll ans = 0;
    se.clear();
    for (auto p : factors[k])
    {
        int tx, ty;
        for (int i = 0; i < 4; ++i)
        {
            tx = x + dx[i] * p.first;
            ty = y + dy[i] * p.second;
            if (check(tx, ty))
            {
                se.insert(Pair(tx, ty));
            }
        }
    }

    for (auto p:se)
    {
        ans += G[p.first][p.second];
    }
    last_ans = ans;
    return ans;
}

inline void restore ()
{
    for (auto p : changed)
    {
        G[p.first][p.second] = 0;
    }
    changed.clear();
}

int main ()
{
#ifdef FILE_IN
    freopen(FILE_IN, "r", stdin);
#endif
//    SYNC
    int T;
    scanf("%d", &T);
    init();
    int Case = 0;
    while (T--)
    {
        last_ans = 0;
        printf("Case #%d:\n", ++Case);
        scanf("%d %d", &n, &m);
        for (int i = 0; i < n; ++i)
        {
            int x, y, k;
            scanf("%d %d %d", &x, &y, &k);
            add(x, y, k);
        }
        for (int i = 0; i < m; ++i)
        {
            int t;
            scanf("%d", &t);
            int x, y, k, w;
            switch (t)
            {
                case 1:
                    scanf("%d %d %d", &x, &y, &k);
                    add(x, y, k, 1);
                    break;
                case 2:
                    scanf("%d %d", &x, &y);
                    remove(x, y);
                    break;
                case 3:
                    scanf("%d %d %d %d", &x, &y, &k, &w);
                    increase(x, y, k, w);
                    break;
                case 4:
                    scanf("%d %d %d", &x, &y, &k);
                    printf("%lld\n", sum(x, y, k));
                    break;
            }
        }
        restore();
    }

#ifdef FILE_IN
    fclose(stdin);
#endif

    return 0;
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,558评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,002评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,024评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,144评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,255评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,295评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,068评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,478评论 1 305
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,789评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,965评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,649评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,267评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,982评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,800评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,847评论 2 351

推荐阅读更多精彩内容

  • 在C语言中,五种基本数据类型存储空间长度的排列顺序是: A)char B)char=int<=float C)ch...
    夏天再来阅读 3,339评论 0 2
  • 一、实验目的 学习使用 weka 中的常用分类器,完成数据分类任务。 二、实验内容 了解 weka 中 explo...
    yigoh阅读 8,511评论 5 4
  • 最好的大V是时间 2)币很大程度上决定了去中心化 没有币;操控链的就是金钱、权利;又回到中心化原点。 3)区块链...
    007独自散步阅读 319评论 0 0
  • 刚刚翻微博的时候翻出一句话"有的人心易变,三头五年就面目全非;有的人心如止水,十万八千里走过,初心不改。"又想起了...
    萧亦行阅读 144评论 2 3
  • 最怕的,是你不知道你不知道。 这是一种很危险的状态,当然,也有人就这么过着一生。 记得小时候上幼儿园,那是个幸福的...
    缓步类阅读 347评论 2 1