[カエル]神JZOJ3799

タイトル

トピックリンク: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] = \和^ {(Y、X) } _ {Y} F [Y
] [S] \] 答え\(\ ^ {N-SUM _ {I} 1} = F [I] [0] \)
アルゴリズムの時間と空間の複雑さをしている\(O(N2メートル^)\) スペースを揚げされます。
実際に、より大きい全ての粒子は、我々を発見した(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(N 2 ^ {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;
}

おすすめ

転載: www.cnblogs.com/stoorz/p/12111312.html