luogu P2000 拯救世界

嘟嘟嘟

题目有点坑,要你求的多少大阵指的是召唤kkk的大阵数 * lzn的大阵数,不是相加。

看到这个限制条件,显然要用生成函数推一推。

比如第一个条件“金神石的块数必须是6的倍数”,就是\(1 +x ^ 6 + x ^ {12} + \ldots\),也就是\(\frac{1 - x ^ {6n}}{1 - x ^ 6}\)。当\(x \in (-1, 1)\)时,就变成了\(\frac{1}{1 - x ^ 6}\)。

剩下的同理。

然后把这10个条件都乘起来,一顿化简,答案就是\(\frac{(n + 1) * (n + 2) * (n + 3) *(n + 4)}{24}\)。

本来想快乐的写高精,但是\(n = 1e5\)还非得用fft。

于是就写了一发,不开O2会TLE飞,开了后TLE最后一个点。然后把fft的预处理改成bin哥的写法后就过了。

#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
#define enter puts("")
#define space putchar(‘ ‘)
#define Mem(a, x) memset(a, x, sizeof(a))
#define In inline
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-8;
const db PI = acos(-1);
const int maxn = 4e6 + 5;
inline ll read()
{
    ll ans = 0;
    char ch = getchar(), last = ‘ ‘;
    while(!isdigit(ch)) last = ch, ch = getchar();
    while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - ‘0‘, ch = getchar();
    if(last == ‘-‘) ans = -ans;
    return ans;
}
inline void write(ll x)
{
    if(x < 0) x = -x, putchar(‘-‘);
    if(x >= 10) write(x / 10);
    putchar(x % 10 + ‘0‘);
}

char a1[maxn];
int n, m, a[maxn], b[maxn];

int len = 1;
struct Comp
{
    db x, y;
    In Comp operator + (const Comp& oth)const
    {
        return (Comp){x + oth.x, y + oth.y};
    }
    In Comp operator - (const Comp& oth)const
    {
        return (Comp){x - oth.x, y - oth.y};
    }
    In Comp operator * (const Comp& oth)const
    {
        return (Comp){x * oth.x - y * oth.y, x * oth.y + y * oth.x};
    }
    friend In void swap(Comp& a, Comp& b)
    {
        swap(a.x, b.x); swap(a.y, b.y);
    }
}c[maxn], d[maxn], omg[maxn], inv[maxn];
int r[maxn];
In void init()
{
    omg[0] = inv[0] = (Comp){1, 0};
    omg[1] = inv[len - 1] = (Comp){cos(2 * PI / len), sin(2 * PI / len)};
    for(int i = 2; i < len; ++i) omg[i] = inv[len - i] = omg[i - 1] * omg[1];
}
In void fft(Comp* a, Comp* omg)
{
    for(int i = 0; i < len; ++i) if(i < r[i]) swap(a[i], a[r[i]]);
    for(int l = 2; l <= len; l <<= 1)
    {
        int q = l >> 1;
        for(Comp* p = a; p != a + len; p += l)
            for(int i = 0; i < q; ++i)
            {
                Comp tp = omg[len / l * i] * p[i + q];
                p[i + q] = p[i] - tp, p[i] = p[i] + tp;
            }
    }
}

In void mul(int* a, int* b)
{
    int tot = max(n, m); len = 1;
    while(len < (tot << 1)) len <<= 1;
    int lim = 0;
    while((1 << lim) < len) ++lim;
    for(int i = 0; i < len; ++i) r[i] = (r[i >> 1] >> 1) | ((i & 1) << (lim - 1));
    for(int i = 0; i < len; ++i) c[i] = d[i] = (Comp){0, 0};
    for(int i = 0; i < n; ++i) c[i] = (Comp){a[i], 0};
    for(int i = 0; i < m; ++i) d[i] = (Comp){b[i], 0};
    init();
    fft(c, omg), fft(d, omg);
    for(int i = 0; i < len; ++i) c[i] = c[i] * d[i];
    fft(c, inv);
    for(int i = 0; i <= len; ++i) a[i] = 0;
    for(int i = 0; i < len; ++i)
    {
        a[i] += (int)(c[i].x / len + 0.5);
        if(a[i] >= 10) a[i + 1] += a[i] / 10, a[i] %= 10;
    }
    n = len;
    while(n - 1 && !a[n - 1]) --n;
//  for(int i = n - 1; i >= 0; --i) printf("%d", a[i]); enter;
}
In void add(int* a, int x, int& n)
{
    a[0] += x;
    for(int i = 0; i < n; ++i)
        if(a[i] >= 10) a[i + 1] += a[i] / 10, a[i] %= 10;
        else break;
    ++n;
    while(n - 1 && !a[n - 1]) --n;
//  for(int i = n - 1; i >= 0; --i) printf("%d", a[i]); enter;
}
In void div(int* a, int x)
{
    static int ret[maxn];
    reverse(a, a + n);
    int tp = 0, cnt = 0;
    for(int i = 0; i < n; ++i)
    {
        tp = tp * 10 + a[i];
        ret[++cnt] = tp / x;
        tp %= x;
    }
    int sta = 1;
    while(sta < cnt && !ret[sta]) ++sta;
    for(int i = sta; i <= cnt; ++i) write(ret[i]); enter;
}

int main()
{
//  freopen("random.in", "r", stdin);
//  freopen("ac.out", "w", stdout);
    scanf("%s", a1);
    m = n = strlen(a1);
    for(int i = 0; i < n; ++i) b[i] = a[i] = a1[n - i - 1] - ‘0‘;
    add(a, 1, n); add(b, 1, m);
    for(int i = 2; i <= 4; ++i)
    {
        add(b, 1, m);
        mul(a, b);
    }
    div(a, 24);
    return 0;
}

原文地址:https://www.cnblogs.com/mrclr/p/10325758.html

时间: 2024-10-18 21:40:21

luogu P2000 拯救世界的相关文章

[题解] Luogu P2000 拯救世界

生成函数板子题...... 要写高精,还要NTT优化......异常dl 这个并不难想啊...... 一次召唤会涉及到\(10\)个因素,全部写出来,然后乘起来就得到了答案的生成函数,输出\(n\)次项的系数就好了. 下面把\(10\)个条件列一下 \[1 + x^6 + x^{12} + \cdots = \frac{1}{1-x^6}\] \[1+x^2+x^3+\cdots+x^9 = \frac{1-x^{10}}{1-x}\] \[1+x^2+x^3+x^4+x^5 = \frac{1

九九乘法表拯救世界【误

Private Sub Command1_Click() Dim i, j As Integer Label1.Caption = " 万岁!世界重新得到了和平!" Form1.Cls For i = 1 To 9 For j = 1 To i Print j; "x"; i; "="; j * i, Next j Print Next i End Sub Private Sub Command2_Click() Form1.Cls Label1

【技术宅拯救世界】在Windows Server2012上利用OpenVPN搭建自己的VPN服务器

写在前面的话:前段时间利用VPN免流特别火,我本来打算买一个,但后来发现其实都是用的OpenVPN搭建的,正好我手上有一个腾讯的云服务器,我一想不如就自己搭建一个吧,省点钱,结果就这样浪费了两天的时间,最大的问题在于网上关于用windows server搭建的教程异常的少,大部分都是cent os并且是脚本搭建的,我看了好多,看得我一头雾水...总算在我折腾服务器两天之后建好了属于自己的第一个VPN服务器,但是免流那块,四川联通失败,浪费了我两天的时间,但是为了避免以后搭建再次搭建VPN时发生问

vijos 1225 拯救世界-紧急集合

这是道带权中位数的题,自己一想好像暑假的时候在 noi-openjudge 那个网站写题的时候看过类似的,那个时候的我蒟蒻, 不知道怎么办? 现在重新想起了这一类题,找个时间攻一下吧!毕竟这道题不难, (只要从左往右扫一次,和从右往左扫一次,我再一次可耻地看了题解),思考了一下二维的情况,应该不难,只是把x坐标和y坐标分开而已,加油! 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #def

#技术男拯救世界# 如何自动跳过12306的「查询失败」

我等屌丝用不起Windows,也没法装哪些高大上的抢票浏览器,只好苦逼的刷12306官网.但是刷12306的过程中老是遇到「查询失败」错误,一旦遇到,刷票就自动中断了,让人非常不爽.于是就自己写了下面这个小脚本,用来跳过失败错误并恢复刷票. 使 用方法:打开任何浏览器,登录12306网站,进入查询/刷票页面,打开开发者工具里的网页控制台(Chrome:查看->开发者 ->JavaScript控制台,Firefox:工具->网页开发者->网页控制台,Safari:先打开「首选项」-&

拯救世界

推导可得 ans=(n+1)(n+2)(n+3)(n+4)/24 于是乎打了一发py mdTLE 然后迫不得已写了一发ntt #include<cstdio> #include<algorithm> #include<iostream> const int mod = 998244353,g=3; const int maxn = 1001000; typedef long long ll; inline int pow(int a,int b,int ans=1){

【模板】生成函数

例如,我们有一个数列{1,6,4,8,5},我们考虑用一个函数来表示这个数列. \(g(x)\)=\(1\)+\(6x^1\)+\(4x^2\)+\(8x^3\)+\(5x^4\) 在这个函数中,每一项的系数为数列中的数,每一项的未知数\(x\)的指数\(i\)代表了这一项的系数是原数列的\(i+1\)项. 那么这个可以做什么呢? 他可以求一类类似背包的题. 比如说: 有A,B两种物品,A种物品至多取2个,B种物品的取得个数必须是5的倍数.请问A,B两种物品的个数加起来的数量为n的方案数. 答案

基督徒如何对&ldquo;世界&rdquo;

基督徒如何对待"世界"呢?这是一个显然的问题,其实也是一个不显然的问题,让我们从圣经经文本身去看这个话题. 当我们去查考圣经的时候,"世界"这个词在和合本圣经更多的是出现在新约圣经中.在旧约圣经中,"世界"这个词大部分都是实体性的指代神创造的这个世界,或者是这个世界的其中一部分,类似迦南,或者其他的地方,只有少数几处会指代一个意思:阴间. 我们列举经文如下: [创 6:11] 世界在 神面前败坏,地上满了强暴. [创 6:12] 神观看世界,见是

手机的次世代:科幻会成为现实吗?

当贝尔在1876年3月10日发明第一台电话机(另一观点认为意大利人安东尼奥·梅乌奇是电话机发明者)时,并没有人想到这个构建了便利通讯方式的工具,会对整个人类产生如此深远的影响. 因为在这之后的一百多年社会发展历程中,这种基于无线通信方式带来的人类文明变革,已经超越了所有历史中的文明时代.在今天的生活中,从普通电话到智能手机的演变过程,也已经将人类推向了一个全新的文明高度,并且在不久远的未来,以手机为主题的通讯设备将有望承载着一个新的时代. 这并非危言耸听,也并非遥不可及.事实上,一些已经逐渐面世