码迷,mamicode.com
首页 > 其他好文 > 详细

【JZOJ3799】青蛙神

时间:2019-12-28 13:28:42      阅读:99      评论:0      收藏:0      [点我收藏+]

标签:xor   eof   没有   质因数   就是   预处理   tps   路径   技术   

题目

题目链接:https://jzoj.net/senior/#main/show/3799
技术图片

思路

如果一个数是完全平方数,当且仅当它分解质因数后,每一个质因数的质数均为偶数。
由于\(n\leq 90\),所以最多有\(24\)个质数。考虑状压。
所以我们预处理出\(prmS[x]\)表示数字\(x\)分解质因数后,指数为奇数的质因数集合。
\(f[x][S]\)表示处理到\(DAG\)中的点\(x\),终点为\(x\)的所有路径中,有多少条指数为奇数的质数集合为\(S\)的路径。
由于是一张\(DAG\),所以不用担心一条路径走过一条边两次。
那么对于\(DAG\)中的每一条边\((y,x)\),我们有
\[f[x][S\ xor\ prmS[x]]=\sum^{(y,x)}_{y}f[y][S]\]
答案是\(\sum^{n}_{i=1}f[i][0]\)
这个算法的时空复杂度均为\(O(n2^m)\),空间会炸。
我们发现,其实所有大于\(\frac{90}{2}\)的质数都是没有用的,因为在\(1\sim n\)中,含有该质因子的数就只有这个质数本身,所以如果一条路径包含这个点,那么这条路径必然会有一个质因子的质数为1。
也就是说,大于\(\frac{90}{2}\)的质数我们都可以根本不用在图中出现,直接删去这个点即可,因为这个点不会造成任何贡献。
那么有用的质因数就只有\(2,3,5,7,11,13,17,19,23,29,31,37,41,43\)\(14\)个了。
这样时空复杂度就降到了\(O(n2^{14})\),可以过掉本题。

代码

#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;

const int N=100,M=8010,MAXN=(1<<14);
const int prime[15]={0,2,3,5,7,11,13,17,19,23,29,31,37,41,43};
int n,m,tot,head[N],prmS[N],in[N];
ll ans,f[N][MAXN];

struct edge
{
    int next,to;
}e[M];

void add(int from,int to)
{
    e[++tot].to=to;
    e[tot].next=head[from];
    head[from]=tot;
}

void topsort()
{
    queue<int> q;
    for (int i=1;i<=n;i++)
        if (!in[i]) q.push(i);
    for (int i=1;i<=n;i++)
        f[i][prmS[i]]=1;
    while (q.size())
    {
        int u=q.front();
        q.pop();
        for (int i=head[u];~i;i=e[i].next)
        {
            int v=e[i].to;
            for (int j=0;j<MAXN;j++)
                f[v][j^prmS[v]]+=f[u][j];
            in[v]--;
            if (!in[v]) q.push(v);
        }
    }
}

int main()
{
    memset(head,-1,sizeof(head));
    scanf("%d%d",&n,&m);
    for (int i=1,x,y;i<=m;i++)
    {
        scanf("%d%d",&x,&y);
        if (x==47||x==53||x==59||x==61||x==67||x==71||x==73||x==79||x==83||x==89) continue;
        if (y==47||y==53||y==59||y==61||y==67||y==71||y==73||y==79||y==83||y==89) continue;
        add(x,y); in[y]++;
    }
    for (int i=2;i<=n;i++)
        for (int p=i,j=1;prime[j]<=p && j<=14;j++)
            if (!(p%prime[j]))
            {
                bool cnt=0;
                for (;!(p%prime[j]);p/=prime[j]) cnt^=1;
                if (cnt) prmS[i]|=(1<<j-1);
            }
    topsort();
    for (int i=1;i<=n;i++)
        if (i!=47&&i!=53&&i!=59&&i!=61&&i!=67&&i!=71&&i!=73&&i!=79&&i!=83&&i!=89)
            ans+=f[i][0];
    printf("%lld",ans);
    return 0;
}

【JZOJ3799】青蛙神

标签:xor   eof   没有   质因数   就是   预处理   tps   路径   技术   

原文地址:https://www.cnblogs.com/stoorz/p/12111312.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!