NOIp2018集训test-9-19(am&pm)
AM
这是一套在长沙考过而且我能记得全部正解的题,然后期望得分300实际得分155。
T1
很套路,随便搞(我当年是怎么花大半场时间写T1并且写出现在两倍长的代码的??)
1 //Achen
2 #include<bits/stdc++.h>
3 #define For(i,a,b) for(int i=(a);i<=(b);i++)
4 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
5 #define Formylove return 0
6 const int N=2e5+5;
7 using namespace std;
8 typedef long long LL;
9 typedef double db;
10 int n,m,cnt[62];
11 LL a[N];
12
13 template<typename T>void read(T &x) {
14 T f=1; x=0; char ch=getchar();
15 while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
16 if(ch=='-') f=-1,ch=getchar();
17 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
18 }
19
20 map<LL,int>mp;
21
22 LL mo(LL x,LL p) { return x>=p?x-p:x;}
23 LL ksc(LL a,LL b,LL p) {
24 if(a>=p) a%=p;
25 if(b>=p) b%=p;
26 if(a<b) swap(a,b);
27 LL bs=a,rs=0;
28 while(b) {
29 if(b&1) rs=mo(rs+bs,p);
30 bs=mo(bs+bs,p);
31 b>>=1;
32 }
33 return rs;
34 }
35
36 #define ANS
37 int main() {
38 #ifdef ANS
39 freopen("meaningless.in","r",stdin);
40 freopen("meaningless.out","w",stdout);
41 #endif
42 read(n); read(m);
43 For(i,1,n) {
44 read(a[i]);
45 For(j,0,59) if(a[i]&(1LL<<j))
46 cnt[j]++;
47 mp[a[i]]++;
48 }
49 For(i,1,m) {
50 int o;
51 LL x,y,p;
52 read(o);
53 if(o==1) {
54 read(x); read(y);
55 if(x==y) continue;
56 if(mp[x]) {
57 int tp=mp[x];
58 For(j,0,59) {
59 if((x&(1LL<<j))&&!(y&(1LL<<j))) {
60 cnt[j]-=tp;
61 }
62 else if(!(x&(1LL<<j))&&(y&(1LL<<j))){
63 cnt[j]+=tp;
64 }
65 }
66 mp[y]+=tp;
67 mp[x]=0;
68 }
69 }
70 else {
71 read(p);
72 LL bs=1LL,ans=0;
73 For(i,0,59) {
74 ans=mo(ans+ksc((LL)cnt[i]*(n-cnt[i])*2,bs,p),p);
75 bs=bs*2LL%p;
76 }
77 printf("%lld\n",ans);
78 }
79 }
80 //cerr<<clock()<<endl;
81 Formylove;
82 }
T2
一开始一直在想数位dp,事实证明当初我不会数位dp现在仍然不会,然后看了下lucas发现很好做啊,结果少了一句话——sum[0][0]没有赋值(手拍就是不靠谱),直接炸了45分。
1 //Achen
2 #include<bits/stdc++.h>
3 #define For(i,a,b) for(int i=(a);i<=(b);i++)
4 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
5 #define Formylove return 0
6 const int N=1000007,p=2333;
7 using namespace std;
8 typedef long long LL;
9 typedef double db;
10 int T,C[p+2][p+2],sum[p+2][p+2];
11 LL n,k,fac[N],inv[N];
12
13 template<typename T>void read(T &x) {
14 T f=1; x=0; char ch=getchar();
15 while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
16 if(ch=='-') f=-1,ch=getchar();
17 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
18 }
19
20 LL lucas(LL n,LL m) {
21 if(n<p&&m<p) return C[n][m];
22 return lucas(n/p,m/p)*lucas(n%p,m%p)%p;
23 }
24
25 LL calc(LL n,LL m) {
26 if(n<=p&&m<=p) return sum[n][m];
27 LL t1=m/p,t2=m%p,rs;
28 if(t1) rs=calc(n/p,t1-1)*calc(n%p,2332)%p;
29 else rs=0;
30 rs=(rs+lucas(n/p,t1)*calc(n%p,t2)%p)%p;
31 return rs;
32 }
33
34 #define ANS
35 int main() {
36 #ifdef ANS
37 freopen("quondam.in","r",stdin);
38 freopen("quondam.out","w",stdout);
39 #endif
40 read(T);
41 For(i,0,p) C[i][0]=1;
42 For(i,1,p) For(j,1,i) C[i][j]=(C[i-1][j-1]+C[i-1][j])%p;
43 sum[0][0]=1;
44 For(i,0,p) {
45 sum[i][0]=1;
46 For(j,1,p) sum[i][j]=(sum[i][j-1]+C[i][j])%p;
47 }
48 while(T--) {
49 read(n); read(k);
50 LL ans=calc(n,k);
51 printf("%lld\n",ans);
52 }
53 //cerr<<clock()<<endl;
54 Formylove;
55 }
T3
对这题影响贼深刻,打t2之前打的t3,以为稳了,结果直接爆0。一是我经常犯的一手写队列就出错,调用队首元素总是把que[ql]直接写成ql,二是写的时候不知为何没开滚动数组,而是把更新签到数组存下来(好像和滚动是一个意思来着,无所谓了),因为要插两次,第二次插之前就复原一次,结果如果k是1的话第一次是没插的,一复原就跳到原来去了,相当于滚动数组某次没做dp却把o^=1。
一开始写的时候sb地把攻击力相同的点合并了,显然是不能合并的,因为种类不同,背包同种类之间是无差的。实际上有没有攻击力相同的点是无所谓的做法是相同的。
1 //Achen
2 #include<bits/stdc++.h>
3 #define For(i,a,b) for(int i=(a);i<=(b);i++)
4 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
5 #define Formylove return 0
6 const int N=200007,P=19260817;
7 using namespace std;
8 typedef long long LL;
9 typedef double db;
10 int n,m,sa[N],tot,sumnow;
11 LL ans,cc[N];
12
13 template<typename T>void read(T &x) {
14 T f=1; x=0; char ch=getchar();
15 while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
16 if(ch=='-') f=-1,ch=getchar();
17 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
18 }
19
20 struct node {
21 int v,cnt;
22 friend bool operator <(const node&A,const node&B) {
23 return A.v>B.v;
24 }
25 }p[505];
26
27 LL mo(LL x) {
28 if(x<0) {
29 int debug=1;
30 }
31 return x<0?x+P:(x>=P?x-P:x);
32 }
33
34 LL f[N],prf[N];
35 int que[N],ql,qr;
36 void ins(int v,int cnt) {
37 if(!cnt) return;
38 For(w,0,v-1) {
39 ql=0; qr=-1;
40 LL tp=0;
41 for(int i=w;i<=m;i+=v) {
42 while(ql<=qr&&(i-que[ql])/v>cnt) {
43 tp=mo(tp-prf[que[ql]]); ql++;
44 }
45 prf[i]=f[i];
46 f[i]=mo(f[i]+tp);
47 tp=mo(tp+prf[i]);
48 que[++qr]=i;
49 }
50 }
51 }
52
53 #define ANS
54 int main() {
55 #ifdef ANS
56 freopen("refrigerator.in","r",stdin);
57 freopen("refrigerator.out","w",stdout);
58 #endif
59 read(n); read(m);
60 For(i,1,n) {
61 read(p[i].cnt); read(p[i].v);
62 }
63 sort(p+1,p+n+1);
64 For(i,1,n) sumnow+=p[i].cnt*p[i].v;
65 f[0]=1;
66 if(sumnow<m) ans++;
67 For(i,1,n) {
68 sumnow-=p[i].cnt*p[i].v;
69 ins(p[i].v,p[i].cnt-1);
70 For(s,max(0,m-sumnow-p[i].v),m-sumnow-1)
71 ans=mo(ans+f[s]);
72 if(p[i].cnt-1) For(j,0,m) f[j]=prf[j];
73 ins(p[i].v,p[i].cnt);
74 }
75 printf("%lld\n",ans);
76 //cerr<<clock()<<endl;
77 Formylove;
78 }
PM
也是一年前做过的,太菜还是做不求来。
T1segment
两种做法,标解是个套路,把每个修改拆成左右两边然后按左边排序,遇见左端点就加进set遇见右端点就erase,每次遇见点的时候上个点到这个点的区间间的最大值就是set里的最大值。
我忘了这个套路,然后很sb地把修改按a大小排序,从大到小覆盖区间,每个区间第一次被覆盖的时候就是它最后的答案。用set维护区间,一开始放进一个(1,n,未覆盖)的点,每次在set里把能覆盖的区间找出来,已经被覆盖的一段连续区间合并,复杂度就很ok。也还是很好写的,stl就是好。
然而我一开始只有80pt,因为1e18的时候r-l已经是Longlong了没取膜,再乘一个int就爆了。
1 //Achen
2 #include<bits/stdc++.h>
3 #define For(i,a,b) for(int i=(a);i<=(b);i++)
4 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
5 #define Formylove return 0
6 const int N=1e5+7,p=998244353;
7 using namespace std;
8 typedef long long LL;
9 typedef double db;
10 int m;
11 LL n,ans;
12
13 template<typename T>void read(T &x) {
14 T f=1; x=0; char ch=getchar();
15 while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
16 if(ch=='-') f=-1,ch=getchar();
17 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
18 }
19
20 struct QS {
21 LL l,r,a;
22 friend bool operator <(const QS&A,const QS&B) {
23 return A.a>B.a;
24 }
25 }q[N];
26
27 struct node {
28 LL l,r;
29 int ok;
30 node(){}
31 node(LL l,LL r,int ok):l(l),r(r),ok(ok){}
32 friend bool operator <(const node&A,const node&B) {
33 return A.r<B.r;
34 }
35 };
36 set<node>s;
37 #define IT set<node>::iterator
38 LL mo(LL x) { return (x%p+p)%p; }
39 LL pf(LL x) { return x*x%p; }
40
41 #define ANS
42 int main() {
43 #ifdef ANS
44 freopen("segment.in","r",stdin);
45 freopen("segment.out","w",stdout);
46 #endif
47 read(n); read(m);
48 For(i,1,m) {
49 read(q[i].l);
50 read(q[i].r);
51 read(q[i].a);
52 }
53 sort(q+1,q+m+1);
54 s.insert(node(1,n,0));
55 For(i,1,m) {
56 node t=node(q[i].l,q[i].r,0);
57 node x;
58 node nx=node(0,0,1),nl=node(0,0,0),nr=node(0,0,0);
59 IT it=s.lower_bound(t);
60 for(;;) {
61 if(it==s.end()) break;
62 x=*it;
63 s.erase(it--);
64 if(x.l>t.l&&x.r<t.r) {
65 if(!x.ok) ans=mo(ans+pf(q[i].a%p)*((x.r-x.l+1)%p)%p);
66 }
67 if(x.r>=t.r) {
68 if(!x.ok) ans=mo(ans+pf(q[i].a%p)*(((t.r-max(t.l,x.l)+1))%p)%p);
69 if(!x.ok&&x.r>t.r) {
70 nr=node(t.r+1,x.r,0);
71 nx.r=t.r;
72 }
73 else nx.r=x.r;
74 }
75 if(x.l<=t.l) {
76 if(!x.ok&&!(x.r>=t.r)) ans=mo(ans+pf(q[i].a%p)*((x.r-t.l+1)%p)%p);
77 if(!x.ok&&x.l<t.l) {
78 nl=node(x.l,t.l-1,0);
79 nx.l=t.l;
80 }
81 else nx.l=x.l;
82 break;
83 }
84 }
85 if(nx.l!=0) s.insert(nx);
86 if(nl.l!=0) s.insert(nl);
87 if(nr.l!=0) s.insert(nr);
88 }
89 printf("%lld\n",ans);
90 //cerr<<clock()<<endl;
91 Formylove;
92 }
T2 hotel
不知道为什么没有切这道题,有时候看到题觉得很麻烦就懒得动脑子去想,就想打个暴力部分分什么的就走,也可能没把题意理解清楚,看漏题上的条件之类的也是我经常犯的错误,题面往往是蕴含很多信息的,需要去理解,但我一看到不能秒懂的题面就会觉得头疼,这类题往往即使简单也做不出来。
前30n^2模拟,中间30线段树维护非0区间的答案。其实读懂题这步就直接通向标解了。
显然是把每个位置现在还能装多少人用线段树维护,题面告诉你这个东西非负,你把线段树区间维护非0段的信息改成维护非最小值的信息,随便处理一下就好了。
1 //Achen
2 #include<bits/stdc++.h>
3 #define For(i,a,b) for(int i=(a);i<=(b);i++)
4 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
5 #define Formylove return 0
6 const int N=3e5+7;
7 using namespace std;
8 typedef long long LL;
9 typedef double db;
10 int n,m,w[N];
11
12 template<typename T>void read(T &x) {
13 T f=1; x=0; char ch=getchar();
14 while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
15 if(ch=='-') f=-1,ch=getchar();
16 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
17 }
18
19 LL sg[N<<2],mi[N<<2],lz[N<<2],sl[N<<2],sr[N<<2];
20 #define lc (x<<1)
21 #define rc ((x<<1)|1)
22 #define mid ((l+r)>>1)
23 LL get_all(LL l) { return (l+1)*l/2; }
24
25 void down(int x,int l,int r) {
26 if(!lz[x]) return;
27 mi[lc]+=lz[x]; lz[lc]+=lz[x];
28 mi[rc]+=lz[x]; lz[rc]+=lz[x];
29 lz[x]=0;
30 }
31
32 void upd(int x,int l,int r) {
33 if(mi[lc]==mi[rc]) {
34 mi[x]=mi[lc];
35 sg[x]=sg[lc]+sg[rc]+sr[lc]*sl[rc];
36 sr[x]=(sr[rc]==r-mid?sr[lc]+r-mid:sr[rc]);
37 sl[x]=(sl[lc]==mid-l+1?sl[rc]+mid-l+1:sl[lc]);
38 }
39 else if(mi[lc]<mi[rc]) {
40 mi[x]=mi[lc]; sg[x]=sg[lc]+get_all(r-mid)+sr[lc]*(r-mid);
41 sl[x]=sl[lc]; sr[x]=sr[lc]+r-mid;
42 }
43 else {
44 mi[x]=mi[rc]; sg[x]=sg[rc]+get_all(mid-l+1)+sl[rc]*(mid-l+1);
45 sr[x]=sr[rc]; sl[x]=sl[rc]+mid-l+1;
46 }
47 }
48
49 void build(int x,int l,int r) {
50 if(l==r) {
51 sg[x]=sl[x]=sr[x]=0;
52 mi[x]=w[l];
53 return;
54 }
55 build(lc,l,mid); build(rc,mid+1,r);
56 upd(x,l,r);
57 }
58
59 void update(int x,int l,int r,int ql,int qr,LL w) {
60 if(l>=ql&&r<=qr) {
61 mi[x]+=w; lz[x]+=w; return ;
62 }
63 down(x,l,r);
64 if(ql<=mid) update(lc,l,mid,ql,qr,w);
65 if(qr>mid) update(rc,mid+1,r,ql,qr,w);
66 upd(x,l,r);
67 }
68
69 LL nlen;
70 LL qry(int x,int l,int r,int ql,int qr) {
71 if(l>=ql&&r<=qr) {
72 if(mi[x]>0) {
73 LL rs=get_all(r-l+1)+nlen*(r-l+1);
74 nlen+=(r-l+1);
75 return rs;
76 }
77 LL rs=sg[x]+nlen*sl[x];
78 if(sr[x]==r-l+1) nlen+=sr[x];
79 else nlen=sr[x];
80 return rs;
81 }
82 down(x,l,r);
83 LL rs=0;
84 if(ql<=mid) rs+=qry(lc,l,mid,ql,qr);
85 if(qr>mid) rs+=qry(rc,mid+1,r,ql,qr);
86 return rs;
87 }
88
89 #define ANS
90 int main() {
91 #ifdef ANS
92 freopen("hotel.in","r",stdin);
93 freopen("hotel.out","w",stdout);
94 #endif
95 read(n); read(m);
96 For(i,1,n) read(w[i]);
97 if(n<=-1000&&m<=-1000) {
98 For(i,1,m) {
99 int o,l,r,x;
100 read(o); read(l); read(r);
101 if(o==1) {
102 read(x);
103 For(j,l,r) w[j]-=x;
104 }
105 else {
106 LL tp=0,ans=0;
107 For(j,l,r) {
108 if(w[j]!=0) tp++;
109 else tp=0;
110 if(j==r||w[j+1]==0)
111 ans+=(tp+1)*tp/2;
112 }
113 printf("%lld\n",ans);
114 }
115 }
116 }
117 else {
118 build(1,1,n);
119 For(i,1,m) {
120 int o,l,r,x;
121 read(o); read(l); read(r);
122 if(o==1) {
123 read(x);
124 update(1,1,n,l,r,-x);
125 }
126 else {
127 nlen=0;
128 LL ans=qry(1,1,n,l,r);
129 printf("%lld\n",ans);
130 }
131 }
132 }
133 //cerr<<clock()<<endl;
134 Formylove;
135 }
T3recursion
我的数学很不好,对数字一类的东西总是很没有感觉,数学好能推柿子或者对数字有感觉的人这题应该是秒切的。但我打了半天表就只看出g是f的前缀和,硬是没看出g[g[]]是i*f的前缀和。
现在还不会证,等ycl大佬分享吧。
打表发现是前缀和以及f[i]代表i出现的次数,就随便搞了(有点像分块优化的感觉?)。
1 //Achen
2 #include<bits/stdc++.h>
3 #define For(i,a,b) for(int i=(a);i<=(b);i++)
4 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
5 #define Formylove return 0
6 const int N=1e6+7,p=998244353;
7 using namespace std;
8 typedef long long LL;
9 typedef double db;
10 int n;
11 int f[N];
12
13 template<typename T>void read(T &x) {
14 T f=1; x=0; char ch=getchar();
15 while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
16 if(ch=='-') f=-1,ch=getchar();
17 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
18 }
19
20 LL mo(LL x) { return x>=p?x-p:x; }
21
22 int F(int n) {
23 if(n==1) f[n]=1;
24 if(!f[n]) {
25 return 1+F(n-F(F(n-1)));
26 }
27 return f[n];
28 }
29
30 LL dc(LL l,LL r) { return (l+r)*(r-l+1)/2%p; }
31
32 #define ANS
33 int main() {
34 #ifdef ANS
35 freopen("recursion.in","r",stdin);
36 freopen("recursion.out","w",stdout);
37 #endif
38 int tot=0;
39 For(i,1,1000000) f[i]=F(i);
40 read(n);
41 int now=2;
42 LL g=1,gg=1;
43 for(int i=2;;i++) {
44 if(now+f[i]>n) {
45 g=mo(g+i*(n-now+1)%p);
46 gg=mo(gg+i*dc(now,n)%p);
47 break;
48 }
49 g=mo(g+i*f[i]%p);
50 gg=mo(gg+i*dc(now,now+f[i]-1)%p);
51 now+=f[i];
52 }
53 printf("%lld %lld\n",g,gg);
54 Formylove;
55 }