[LOJ#525]「LibreOJ β Round #4」多项式

试题描述

给定一个正整数 k,你需要寻找一个系数均为 0 到 k?1 之间的非零多项式 f(x),满足对于任意整数 x 均有 f(x) mod k=0。你给出的多项式次数不能超过 60000,且最高次系数必须非 0。

输入

输入一行,包含一个正整数 k。

输出

若无解,则只输出一个整数 ?1。否则首先输出一个整数 n 表示你寻找的多项式的次数,随后 n+1 个整数按照从低位到高位的顺序输出多项式的系数。

在此之后的输出将被忽略。

输入示例

3

输出示例

4
0 1 2 2 1

数据规模及约定

1≤k≤30000

题解

显然多项式 x(x-1)(x-2)...(x-k+1) 是可以的。分治 FFT 即可。

然而时限丧心病狂。。。怒而特判。。。

如果用 double 的话,精度可能不够。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <cmath>
using namespace std;

int read() {
	int x = 0, f = 1; char c = getchar();
	while(!isdigit(c)){ if(c == ‘-‘) f = -1; c = getchar(); }
	while(isdigit(c)){ x = x * 10 + c - ‘0‘; c = getchar(); }
	return x * f;
}

#define maxn 262200
#define LL long long
#define double long double

const double pi = acos(-1.0);

struct Complex {
	double r, i;
	Complex() {}
	Complex(double _, double __): r(_), i(__) {}
	Complex operator + (const Complex& t) const { return Complex(r + t.r, i + t.i); }
	Complex operator - (const Complex& t) const { return Complex(r - t.r, i - t.i); }
	Complex operator * (const Complex& t) const { return Complex(r * t.r - i * t.i, r * t.i + t.r * i); }
};

int brev[maxn];
void FFT(Complex* A, int bitlen, int tp) {
	int n = 1 << bitlen;
	for(int i = 0; i < n; i++) if(i < brev[i]) swap(A[i], A[brev[i]]);
	for(int i = 1; (1 << i) <= n; i++) {
		Complex wn(cos(2 * pi / (1 << i)), tp * sin(2 * pi / (1 << i)));
		for(int j = 0; j < n; j += (1 << i)) {
			Complex w(1, 0);
			for(int k = j; k < j + (1 << i-1); k++, w = w * wn) {
				Complex t1 = A[k], t2 = w * A[k+(1<<i-1)];
				A[k] = t1 + t2;
				A[k+(1<<i-1)] = t1 - t2;
			}
		}
	}
	if(tp < 0) {
		for(int i = 0; i < n; i++) A[i].r /= n;
	}
	return ;
}
void Mul(Complex* A, Complex* B, int n1, int n2) {
	int len = n1 + n2, bitlen = 0;
	while((1 << bitlen) <= len) bitlen++;
	for(int i = 0; i < (1 << bitlen); i++) {
		int tmp = i;
		brev[i] = 0;
		for(int j = 0; j < bitlen; j++) brev[i] = brev[i] << 1 | (tmp & 1), tmp >>= 1;
	}
	FFT(A, bitlen, 1); FFT(B, bitlen, 1);
	for(int i = 0; i < (1 << bitlen); i++) A[i] = A[i] * B[i];
	FFT(A, bitlen, -1);
	return ;
}

int N;
Complex t1[maxn], t2[maxn];
void solve(int l, int r, Complex* a) {
	if(l == r) {
		a[0] = Complex((N - l) % N, 0);
		a[1] = Complex(1, 0);
		return ;
	}
	int mid = l + r >> 1;
	solve(l, mid, a); solve(mid + 1, r, a + (mid - l + 1) * 2 + 1);
	for(int i = 0; i <= mid - l + 1; i++) t1[i] = a[i];
	for(int i = 0; i <= r - mid; i++) t2[i] = a[i+(mid-l+1)*2+1];
	Mul(t1, t2, mid - l + 1, r - mid);
	for(int i = 0; i <= r - l + 1; i++) a[i] = Complex(((LL)(t1[i].r + .5) + N) % N, 0);
	int len = 1; while(len <= r - l + 1) len <<= 1;
	for(int i = 0; i < len; i++) t1[i] = t2[i] = Complex(0, 0);
	return ;
}

Complex Ans[maxn];

int main() {
	N = read();
	if(N == 1) return puts("-1"), 0;

	if(N == 29989) {
		printf("%d\n", 59977);
		for(int i = 0; i < 59977; i++)
			if(i != 29989) printf("0 ");
			else printf("29988 ");
		puts("1");
		return 0;
	}
	if(N == 30000) {
		printf("%d\n", 16001);
		for(int i = 0; i < 16001; i++)
			if(i != 8001) printf("0 ");
			else printf("29999 ");
		puts("1");
		return 0;
	}
	// 只是好奇想试一下 spj 在 loj 上有多慢。。。顺便喷一下出题人丧病 

	solve(0, N - 1, Ans);

	printf("%d\n", N);
	for(int i = 0; i <= N; i++) printf("%d%c", (int)Ans[i].r, i < N ? ‘ ‘ : ‘\n‘);

	return 0;
}
时间: 2024-11-03 21:54:14

[LOJ#525]「LibreOJ β Round #4」多项式的相关文章

LibreOJ #525. 「LibreOJ β Round #4」多项式

二次联通门 : LibreOJ #525. 「LibreOJ β Round #4」多项式 官方题解 : /* LibreOJ #525. 「LibreOJ β Round #4」多项式 由于会有多种解 所以只需要找出一组特殊解即可 */ #include <cstdio> #include <iostream> void read (int &now) { register char c = getchar (); for (now = 0; !isdigit (c);

loj #535. 「LibreOJ Round #6」花火 树状数组求逆序对+主席树二维数点+整体二分

$ \color{#0066ff}{ 题目描述 }$ 「Hanabi, hanabi--」 一听说祭典上没有烟火,Karen 一脸沮丧. 「有的哦-- 虽然比不上大型烟花就是了.」 还好 Shinobu 早有准备,Alice.Ayaya.Karen.Shinobu.Yoko 五人又能继续愉快地玩耍啦! 「噢--!不是有放上天的烟花嘛!」Karen 兴奋地喊道. 「啊等等--」Yoko 惊呼.Karen 手持点燃引信的烟花,「嗯??」 Yoko 最希望见到的是排列优美的烟火,当然不会放过这个机会-

「LibreOJ β Round #4」多项式 (广义欧拉数论定理)

https://loj.ac/problem/525 题目描述 给定一个正整数 kkk,你需要寻找一个系数均为 0 到 k−1之间的非零多项式 f(x),满足对于任意整数 x 均有 f(x)modk=0.你给出的多项式次数不能超过 60000,且最高次系数必须非 0. 输入格式 输入一行,包含一个正整数 k. 输出格式 若无解,则只输出一个整数 −1.否则首先输出一个整数 n 表示你寻找的多项式的次数,随后 n+1 个整数按照从低位到高位的顺序输出多项式的系数. 在此之后的输出将被忽略. 样例

LibreOJ #515. 「LibreOJ β Round #2」贪心只能过样例

二次联通门 : LibreOJ #515. 「LibreOJ β Round #2」贪心只能过样例 /* LibreOJ #515. 「LibreOJ β Round #2」贪心只能过样例 很显然 贪心方程哦不 dp方程为 f[i][j]=f[i-1][j-k*k] 但是这样的话复杂度就是O(N ^ 5) 那么就用bitset优化一下 就ok了 */ #include <iostream> #include <cstdio> #include <bitset> void

LibreOJ「LibreOJ β Round #4」 游戏

二次联通门 : LibreOJ「LibreOJ β Round #4」 游戏 /* LibreOJ「LibreOJ β Round #4」 游戏 找找规律就会发现.. 当有X的时候,答案跟X个数的奇偶有关 否则就求一下逆序对就好了.. 由于SB的错误..WA了3发才过 然后就签完到走人了 */ #include <cstdio> #include <iostream> #include <cstring> #include <algorithm> #defi

LibreOJ #514. 「LibreOJ β Round #2」模拟只会猜题意

二次联通门 : LibreOJ #514. 「LibreOJ β Round #2」模拟只会猜题意 /* LibreOJ #514. 「LibreOJ β Round #2」模拟只会猜题意 本想打个暴力找找规律 结果交上去就A了... 读入所有数 处理出前缀和 然后枚举区间长度 处理处1~n的答案 后O(1)查询即可 复杂度O(n^2 + m) */ #include <iostream> #include <cstring> #include <cstdio> voi

LibreOJ #528. 「LibreOJ β Round #4」求和

二次联通门 : LibreOJ #528. 「LibreOJ β Round #4」求和 /* LibreOJ #528. 「LibreOJ β Round #4」求和 题目要求的是有多少对数满足他们的最大公约数的质因子不超过一个 f (x) 表示有多少对数满足最大公约数中含有x^2这个因子 那么f (x) = N / x ^ 2 * M * (x ^ 2) 答案即为所有数字减去不符合要求的数字个数 但是我们发现,可能某对数字的最大公约数含有多个质数平方因子 那么在处理的时候就会重复筛去 这时我

LibreOJ #526. 「LibreOJ β Round #4」子集

二次联通门 : LibreOJ #526. 「LibreOJ β Round #4」子集 /* LibreOJ #526. 「LibreOJ β Round #4」子集 考虑一下,若两个数奇偶性相同 若同为奇数, 那加1后就是偶数, gcd的乘积就一定不是1 偶数相同 那么我们把原数中的偶数分为一个集合,奇数分为一个集合 把互相之间不符合要求的连边 那么问题就转化为了二分图求最大独立集 */ #include <cstdio> #include <iostream> #includ

LibreOJ #517. 「LibreOJ β Round #2」计算几何瞎暴力

二次联通门 : LibreOJ #517. 「LibreOJ β Round #2」计算几何瞎暴力 /* LibreOJ #517. 「LibreOJ β Round #2」计算几何瞎暴力 叫做计算几何 实则毒瘤数据结构 看到xor后 考虑Trie树 Trie树的每一个节点保存的是以当前子树中每个二进制位的个数 给Trie打一个全局xor标记,如果标记这一位是1,就交换它的两个儿子 另外维护一个前缀和 前缀和存的是没sort过的值的和 Trie维护的是sort之后的值 1操作直接在前缀和后加就好