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 }
View Code

 

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 }
View Code

 

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 }
View Code

 

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 }
View Code

 

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 }
View Code

 

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 }
View Code

 

posted @ 2018-09-20 22:11  啊宸  阅读(119)  评论(0编辑  收藏  举报