JZOJ3799青蛙神
Posted stoorz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JZOJ3799青蛙神相关的知识,希望对你有一定的参考价值。
题目
题目链接:https://jzoj.net/senior/#main/show/3799
思路
如果一个数是完全平方数,当且仅当它分解质因数后,每一个质因数的质数均为偶数。
由于(nleq 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})的质数都是没有用的,因为在(1sim 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青蛙神的主要内容,如果未能解决你的问题,请参考以下文章