T1
题目大意
从前有一个国家,国力繁盛。然而众所周知,一旦一个国家强大了起来,那么这个国家一定会有许多奸臣想要上位。所以来进谏的人无论是谁,无论提出的是什么建议,都有可使国家走向灭亡。
郭紫丽现在就身处这个国家之中,但是她不希望国家出现这种情况。所以她希望给国王出主意。
然而旁边的大臣美国恶女同样也知道这个定律,所以她看到郭紫丽来进谏时,断定她一定是奸臣。
郭紫丽为了证明自己不是奸臣,就需要在智力上打败美国恶女。什么智力游戏呢?当然是下棋了。
美国恶女给出了一个n×m的棋盘,第i行第j列的格子上有一个生命值为 a i , j a_{i,j} ai,j, 的小兵。郭紫丽需要每次吸取一个小兵的生命值以提升自己的能力,但郭紫丽是一个有分寸的人,她不一定会把某个小兵的生命值全部吸完,但她至少会吸取一点。每次郭紫丽吸取完后,美国恶女也会进行一次同样的操作。
为了体现自己作为大臣的气度,美国恶女将游戏简化了一下。郭紫丽可以任意选取一行的小兵来进行这个游戏,也就是说,选好之后,每一个操作只能在这一行上进行。美国恶女又说,如果谁吸取了那一行最后一个小兵的最后一点生命值,那么这个人就会因为守护之力成为胜者。
郭紫丽当然不希望自己输掉,所以她会把棋盘上每一个小兵的生命值告诉你,希望你告诉她,有多少种选行的方式能够获得胜利。但为了不让自己作弊被发现,郭紫丽每次询问都会给出一个区间[l,r],你只能在第[l,r]行中选择。
Input
第一行,两个数n,m表示棋盘的大小。
第二行至第n+1 行,每行m个正整数,第i + 1行第j列上的数表示第i行第j列格子上小兵的生命值。第n+2 行,一个整数Q,表示询问或修改次数。
接下来 Q 行,每行第一个数是 opt ,表示操作编号。如果 opt = 1,后面跟着 2 个数 l,r 表示一次询问操作。如果 opt = 2,则后面跟着五个整数 x1,y1,x2,y2,p。表示将以(x1,y1)为左上角,(x2,y2)为右下角的矩形每个格子上的小兵的生命值都异或p。
Output
输出若干行。对于每一个 opt = 1,输出一个数,表示有多少行小兵能使郭紫丽一定获胜。
n
×
m
≤
100000
,
Q
≤
100000
n\times m\le 100000,Q\le 100000
n×m≤100000,Q≤100000
然而美国恶女也不希望郭紫丽那么容易就获得胜利,所以美国恶女会随时改变棋盘上兵的生命值。请你帮助郭紫丽解决这个问题。
sol
SG博弈,某一行能赢当且仅当这一行生命值xor起来为零。所以可以把n*m矩阵压缩成n行,操作相当于区间xor,区间查多少的数不为零。
nq暴力可以水过。
正解是分块,设 f [ i ] [ j ] f[i][j] f[i][j]为第i块j出现过多少次, t a g [ i ] tag[i] tag[i]为第i块的标记。修改时小块暴力,更改 f f f,大块打标记。查询时小块暴力,大块查询有多少个数等于 t a g tag tag,可以算出有多少个0,总数减0数就是答案。
T2
题目大意
求
∑
k
=
1
⌊
n
2
⌋
C
(
n
−
k
k
)
\sum_{k=1}^{\lfloor\frac{n}{2}\rfloor}C(_{n-k}^k)
k=1∑⌊2n⌋C(n−kk)
答案对998244353取模,
n
≤
1
0
18
n\le 10^{18}
n≤1018。
sol
打表可以发现,答案为 f i b n − 1 fib_n-1 fibn−1,所以直接矩阵快速幂。
证明:题目其实要我们求杨辉三角的某对角线减
C
(
n
0
)
C(_n^0)
C(n0),先不管减1,杨辉三角的计算过程如下:
所以每一对角线值为上两个对角线值之和。
证毕。
T3
题目大意
因式分解。
Input
第一行一个数 n , n ≤ 10 n,n\le 10 n,n≤10,表示多项式的次数。
第二行有 n + 1 n+1 n+1个数,表示多项式从高到低每一项的系数。保证最高次项不为 0 0 0,系数 ≤ 1 0 6 \le 10^6 ≤106。
Output
一行一个字符串,表示因式分解后的结果。
你的输出需要遵循以下原则:
- 未知数用代 x x x替。
- 若有可提取的常数,需提取出来放在最前面。例如, 2 x + 4 2x+4 2x+4应写成 2 ( x + 2 ) 2(x+2) 2(x+2)。
- 若最高次项是负数,则需单独提出来,如 − x + 2 −x+2 −x+2应写成 − ( x − 2 ) −(x−2) −(x−2)。
- 若分解出来有单项式,需放在最前面(常数项之后),例如 x 2 + 2 x x^2+2x x2+2x应写成 x ( x + 2 ) x(x+2) x(x+2)而不是 ( x + 2 ) x (x+2)x (x+2)x。
- 其余分解出来的式子按照常数项从小到大排列。例如 ( x + 3 ) ( x − 1 ) (x+3)(x−1) (x+3)(x−1)应写成 ( x − 1 ) ( x + 3 ) (x−1)(x+3) (x−1)(x+3)
保证原式可以分解成若干个最高次数为 1 的单项式或多项式之积,不会有相同的项(即不会出现 ( x − 1 ) 2 (x-1)^2 (x−1)2之类的式子),系数及常数项都是整数,分解出来的多项式一次项系数为1。
形象一点,以下式子是不会给出的:
2 x 2 + 3 x + 1 = ( 2 x + 1 ) ( x + 1 ) 2x^2+3x+1=(2x+1)(x+1) 2x2+3x+1=(2x+1)(x+1),因为出现了一次项系数为 2 的因式。
x 2 + 2 x + 1 = ( x + 1 ) 2 x^2+2x+1=(x+1)^2 x2+2x+1=(x+1)2,因为出现了平方项。
x 3 + 2 x 2 + 2 x + 1 = ( x 2 + x + 1 ) ( x + 1 ) x^3+2x^2+ 2x+1=(x^2+x+1)(x+1) x3+2x2+2x+1=(x2+x+1)(x+1),因为出现了最高次数为 2 的因式。
x 2 + 5 2 x + 1 = ( x + 2 ) ( x + 1 2 ) x^2+\frac{5}{2}x+1=(x+2)(x+\frac{1}{2}) x2+25x+1=(x+2)(x+21),因为出现了分数。
Sample
Input
4
2 − 14 14 30 0
Output
2(x−5)(x−3)(x+1)
sol
我写了一个dfs,居然有50分。
正解其实十分简单,先把常数和单项式提出来。考虑一件事,若 x + k x+k x+k是原式的一个因式,则把 x = − k x=-k x=−k带入原式一定值为0,反之亦然。
所以可以从 1 0 6 10^6 106枚举到 − 1 0 6 -10^6 −106,依次代入原式,值为0则发现一个因式。
有一个问题, ( 1 0 6 ) 10 (10^6)^{10} (106)10,爆long long了,可以像哈希判等的方法,取模后判等。由于代码过于简单,可以写双哈希。
code:
#include<bits/stdc++.h>
using namespace std;
const int mod1=1e9+7,mod2=1e9+9;
long long a[15],b;
inline long long read()
{
long long x=0;
int f=1;
char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';x=(x<<1)+(x<<3)+(ch^48),ch=getchar());
return x*f;
}
int main()
{
freopen("fenty.in","r",stdin);
freopen("fenty.out","w",stdout);
int n=read();
for(int i=n;~i;i--)
a[i]=read();
b=a[n];//常数
for(int i=n;~i;i--)
a[i]/=b;
if(b!=1)
{
if(b==-1)putchar('-');
else printf("%lld",b);
}
if(!a[0])//单项式
{
for(int i=0;i<n;i++)a[i]=a[i+1];
n--;
putchar('x');
}
for(int i=1e6;i>=-1e6;i--)if(i!=0)
{
int ans1=0,ans2=0,p1=1,p2=1;
for(int j=0;j<=n;j++)
{
ans1=(ans1+a[j]%mod1*p1)%mod1;
ans2=(ans2+a[j]%mod2*p2)%mod2;
p1=1ll*p1*i%mod1;
p2=1ll*p2*i%mod2;
}
if(!ans1&&!ans2)//判等
{
printf("(x");
if(i<0)putchar('+');
printf("%d)",-i);
}
}
puts("");
return 0;
}