zoukankan      html  css  js  c++  java
  • 【Luogu P2150】[NOI2015] 寿司晚宴

    链接:

    洛谷

    博客园

    题目大意:

    (n-1) 个数,第 (i) 数是 (i+1)。在这其中选两组数,求这两组数不互质的方案数。

    (nleq500)

    正文:

    30pts:

    分解质因数,在 (nleq30) 以内的素数只有 (10) 个,设 (f_{i,a,b}) 表示当前操作到第 (i) 个数,第一组的素数集合是 (a),第二组的素数集合是 (b) 的方案数。

    于是可以这么转移:

    [f_{i,a,b}Rightarrowleft{egin{matrix} f_{i+1,acup k,b} & (bcap k=varnothing)\ f_{i+1,a,bcup k} & (acap k=varnothing) end{matrix} ight.]

    进行滚动数组,还可以优化空间。

    时间复杂度 (mathcal{O}(2^{20}n))

    100pts:

    一个小于等于 (n) 的数只有若干个小于等于 (sqrt{n}) 的小质因数和最多一个大于 (sqrt{n}) 的大质因数。因为题目中有给定要互质,那么含有大质因数的数要么全分到 (a) 要么全分到 (b),那么再设 (g_{a,b},h_{a,b}) 分别表示当前有大质因数的数全分给 (a)(b) 的方案数。然后对每个数按大质因数分组(若没有,自己为独立一组),按组统计,合并。合并时,(f_{a,b}=g_{a,b}+h_{a,b}-f_{a,b}),减去的是两组重复计算的两组都没有分到任何一个有大质因数的数的方案数。

    代码:

    const int N = 510;
    
    inline ll READ()
    {
    	ll x = 0, f = 1;
    	char c = getchar();
    	while (c != '-' && (c < '0' || c > '9')) c = getchar();
    	if (c == '-') f = -f, c = getchar();
    	while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar();
    	return x * f;
    }
    
    int n;
    ll p;
    int pri[10] = {2, 3, 5, 7, 11, 13, 17, 19};
    
    struct Val
    {
    	int val, part1, part2;
    	Val(){part2 = -1;} 
    	void Set(int x)
    	{
    		part2 = 0;
    		val = x;
    		for (int i = 0; i < 8; i++)
    			for (; !(x % pri[i]); x /= pri[i]) part1 |= 1 << i; 
    		if (x != 1) part2 = x;
    	}
    	bool operator < (Val &a) const
    	{
    		return part2 < a.part2;
    	}
    }a[N];
    
    ll f[N][N], g[N][N], h[N][N], ans;
    
    int main()
    {
    	n = READ(), p = READ(); 
    	for (int i = 1; i < n; i++) a[i].Set(i + 1);
    	
    	sort (a + 1, a + n);
    	
    	f[0][0] = 1;
    	for (int i = 1; i < n; i++)
    	{
    		if (i == 1 || a[i].part2 != a[i - 1].part2 || !a[i].part2)
    		{
    			memcpy(g, f, sizeof g);
    			memcpy(h, f, sizeof h);
    		}
    		for (int j = 256; j >= 0; j--)
    			for (int k = 256; k >= 0; k--)
    				if(!(j & k))
    				{
    					if (!(a[i].part1 & k)) (g[j | a[i].part1][k] += g[j][k]) %= p;
    					if (!(a[i].part1 & j)) (h[j][k | a[i].part1] += h[j][k]) %= p;
    				}
    		if (i == n - 1 || a[i].part2 != a[i + 1].part2 || !a[i].part2)
    		{
    			ans = 0;
    			for (int j = 0; j <= 256; j++)
    				for (int k = 0; k <= 256; k++)
    					if(!(j & k)) f[j][k] = (g[j][k] + h[j][k] + p - f[j][k]) % p, ans = (ans + max(f[j][k], 0ll)) % p;
    			if (i == n - 1) printf ("%lld
    ", ans);
    		}
    	}
    	
    	return 0;
    }
    
  • 相关阅读:
    理解javascript 对象,原型对象、闭包
    JSON数据理解
    css 盒模型相关样式
    神奇的CSS3选择器
    设计模式六大原则
    java反射机制性能优化
    一份关于jvm内存调优及原理的学习笔记
    浅谈http请求数据分析
    Apache+Tomcat部署负载均衡(或集群)
    同台电脑部署多组Tomcat负载均衡(或集群)
  • 原文地址:https://www.cnblogs.com/GJY-JURUO/p/14769806.html
Copyright © 2011-2022 走看看