2018-08-11考试

考试爆炸祭…
暴力分那么高,打什么正解

结果

题面

T1

T2

T3

题解

T1

一眼二分答案,结果写错了爆5分

T2

一眼看到这个:

对于所有编号为奇数的数据:$a_i=0, i∈[0,7]$;

于是大力贪心骗到了$65pts$
正解差分约束???我还看到过???

T3

我要好好写一下这一题的题解
暴力80分我还来想正解,SHIFT

最近学了一个叫做$Generating\;Function$的东西
于是对于一个区间$[l, r]$,有

$$G(x)=\prod_{i=l}^r(a_ix+1)$$
因为$k<=10$
所以可以维护母函数前$10$项系数
$pushup$很好写,就是一个多项式乘法
$pushdown$的取反很好写,只要考虑奇数项
区间加则不那么好写,(毒瘤线段树)
令$[x^k]$表示$G(x)$中$x^k$的系数
$$\therefore[x^k] = \sum_{i_1<i_2<i_3<…<i_k}\prod_{j=1}^ka_{i_j}$$
$$\because new[x^k] = \sum_{i_1<i_2<i_3<…<i_k}\prod_{j=1}^k(a_{i_j} + c)$$
$\therefore$对于每一个展开式中的$l$
$\prod_{j=1}^la_{i_j}$与$\prod_{j=1}^{k-l}a_{i_j^{,}}$一一对应
又$\because \prod_{j=1}^{k-l}a_{i_j^{,}}$有$\binom{len-l}{k-l}$个
$\therefore$这里贡献的答案为$c^{k-l}\binom{len-l}{k-l}\prod_{j=1}^la_{i_j}$
$$\therefore new[x^k]=\sum_{j=0}^{k-1}\binom{len-j}{k-j}[x^j]c^{k-j}$$
于是就可以$pushdown$了
注意指针的问题!!!

代码

T1

最后AC的代码让我自己都懵

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include<bits/stdc++.h>
#define RG register
#define file(x) freopen(#x".in", "r", stdin);freopen(#x".out", "w", stdout);
#define clear(x, y) memset(x, y, sizeof(x));
using namespace std;

inline int read()
{
int data=0, w=1;
char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') w=-1, ch=getchar();
while(ch>='0'&&ch<='9') data=(data<<3)+(data<<1)+(ch^48), ch=getchar();
return data*w;
}

const int maxn(1e5+10);
int x[maxn], y[maxn], n, m, qx, qy;
inline bool check(int mid)
{
long long a = 1ll * y[mid] * qx;
long long b = 1ll * x[mid] * qy;
long long c = 1ll * x[mid] * y[mid];
return c <= (a + b);
}

int main()
{
n = read();
for(RG int i=1;i<=n;i++) x[i]=read();
for(RG int i=1;i<=n;i++) y[i]=read();
sort(x+1, x+n+1); sort(y+1, y+n+1);
m = read();
while(m--)
{
qx = read(); qy = read();
int l = 0, r = n;
while(l<r)
{
int mid(l+r>>1);
if(check(mid + 1)) l = mid + 1;
else r = mid;
}
printf("%d\n", l);
}
return 0;
}

T2

没有

T3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#include<bits/stdc++.h>
#define RG register
#define file(x) freopen(#x".in", "r", stdin);freopen(#x".out", "w", stdout);
#define clear(x, y) memset(x, y, sizeof(x));
using namespace std;

inline int read()
{
int data=0, w=1;
char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') w=-1, ch=getchar();
while(ch>='0'&&ch<='9') data=(data<<3)+(data<<1)+(ch^48), ch=getchar();
return data*w;
}

const int maxn(50010), mod(1e9+7);
int tree[maxn << 2][11], sum[maxn << 2], n, a[maxn], m, c[maxn][11];
bool mul[maxn << 2];

inline int fastpow(int x, int y)
{
int ans=1;
while(y)
{
if(y&1) ans=1ll*ans*x%mod;
x=1ll*x*x%mod; y>>=1;
}
return ans;
}

#define son(i) ((root<<1)|i)
inline void pushup(int root, int l, int r)
{
clear(tree[root], 0);
int mid=l+r>>1, l1=min(mid-l+1, 10), l2=min(r-mid, 10);
for(RG int i=0;i<=l1;i++)
for(RG int j=0;j<=l2 && i+j<=10;j++)
tree[root][i+j]=(1ll*tree[root][i+j]+1ll*tree[son(0)][i]*tree[son(1)][j]%mod)%mod;
}

void build(int root=1, int l=1, int r=n)
{
if(l==r) { tree[root][1]=a[l]; tree[root][0]=1; return; }
int mid(l+r>>1);
build(son(0), l, mid); build(son(1), mid+1, r);
pushup(root, l, r);
}

inline void dowork(int root, int l, int r, int v)
{
int len=r-l+1, cnt=min(len, 10);
for(RG int i=cnt;~i;i--)
for(RG int j=i-1;~j;j--)
tree[root][i]=(1ll*tree[root][i]+1ll*(1ll*tree[root][j]*c[len-j][i-j]%mod)*fastpow(v, i-j)%mod)%mod;
sum[root]=(1ll*sum[root]+1ll*v)%mod;
}

inline void rev(int root)
{
for(RG int i=1;i<=10;i++)
if(i & 1) tree[root][i]=(mod-tree[root][i])%mod;
mul[root]^=1; sum[root]=(mod-sum[root])%mod;
}

inline void pushdown(int root, int l, int r)
{
if(l==r) return;
if(mul[root]) { mul[root]=0; rev(son(0)); rev(son(1)); }
if(sum[root]!=0)
{
int mid(l+r>>1);
dowork(son(0), l, mid, sum[root]);
dowork(son(1), mid+1, r, sum[root]);
sum[root]=0;
}
}

void update_add(int ql, int qr, int v, int root=1, int l=1, int r=n)
{
if(r<ql || qr<l) return;
if(ql<=l && r<=qr) { dowork(root, l, r, v); return; }
pushdown(root, l, r);
int mid(l+r>>1);
update_add(ql, qr, v, son(0), l, mid);
update_add(ql, qr, v, son(1), mid+1, r);
pushup(root, l, r);
}

void update_rev(int ql, int qr, int root=1, int l=1, int r=n)
{
if(r<ql || qr<l) return;
if(ql<=l && r<=qr) { rev(root); return; }
pushdown(root, l, r);
int mid(l+r>>1);
update_rev(ql, qr, son(0), l, mid);
update_rev(ql, qr, son(1), mid+1, r);
pushup(root, l, r);
}

int *query(int ql, int qr, int root=1, int l=1, int r=n)
{
if(ql<=l && r<=qr) return tree[root];
pushdown(root, l, r);
int mid=l+r>>1, *x=NULL, *y=NULL, *z;
if(ql<=mid) x=query(ql, qr, son(0), l, mid);
if(qr>mid) y=query(ql, qr, son(1), mid+1, r);
if(x==NULL) return y;
if(y==NULL) return x;
z=new int[11]; clear(z, 0);
for(RG int i=0;i<=10;i++)
for(RG int j=0;j<=10 && i+j<=10;j++)
z[i+j]=(1ll*z[i+j]+1ll*x[i]*y[j]%mod)%mod;
return z;
}

int main()
{
n = read(); m = read();
c[0][0]=1;
for(RG int i=1;i<=n;i++)
{
c[i][0]=1;
for(RG int j=1;j<=i && j<=10;j++)
c[i][j]=(1ll*c[i-1][j-1]+1ll*c[i-1][j])%mod;
}
for(RG int i=1;i<=n;i++) a[i]=(1ll*read()+1ll*mod)%mod;
build();
while(m--)
{
int opt=read(), x=read(), y=read(), z;
switch(opt)
{
case 1:
z=(1ll*read()+1ll*mod)%mod; update_add(x, y, z); break;
case 2:
update_rev(x, y); break;
case 3:
z=read(); printf("%d\n", *(query(x, y)+z)); break;
}
}
return 0;
}

是不是很短

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×