NOIp2018集訓test-10-15 (bike day4)
這是一套簡單題,這幾天的考試讓bike老爺感覺很絕望,說實話我也確實不知道還能怎麼更簡單了。
這幾天的題換做llj、sxy應該都能輕鬆AK吧,至少隨便考個250+應該不是問題吧,我越來越覺得覺得我跟他們的差距真的是非常非常大,dcoier跟其他學校的大佬的差距更是如此。我不知道我之前沒有自知之明的時候對自己的定義是怎麼樣的,但是現在我發現我大概真的是一個堪堪noip一等獎水平的選手。
已經不知道該怎麼辦了,我甚至很想自暴自棄地大喊,我已經涼了!!dcoi沒有救的!!每一屆每一屆地下去都會涼透的!!
B 君的第一題 (changchun)
這是一道講過的數學題,然而我實在太菜並不記得怎麼做。
然後寫了個樹dp,似乎遞迴爆棧了只有90。f[x][0]表示x的子樹中與x不相連的聯通塊個數的期望,f[x][1]表示與x相連的聯通塊個數的期望,也就是有點和x相連的概率,就可以轉移了。
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=1000000007;
7 typedef long long LL;
8 typedef double db;
9 using namespace std;
10 int n;
11 LL pr[N],inv=500000004;
12
13 template<typename T> void read(T &x) {
14 char ch=getchar(); x=0; T f=1;
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 int ecnt,fir[N],nxt[N<<1],to[N<<1];
21 void add(int u,int v) {
22 nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v;
23 nxt[++ecnt]=fir[v]; fir[v]=ecnt; to[ecnt]=u;
24 }
25
26 LL f[N][2],son[N];
27 void dfs(int x,int fa) {
28 son[x]=0;
29 for(int i=fir[x];i;i=nxt[i]) if(to[i]!=fa) {
30 int y=to[i];
31 son[x]++;
32 dfs(y,x);
33 f[x][0]=(f[x][0]+(f[y][0]+f[y][1]*inv%p)%p)%p;
34 }
35 f[x][1]=(pr[n]-pr[n-son[x]]+p)%p;
36 }
37
38 #define ANS
39 int main() {
40 #ifdef ANS
41 freopen("changchun.in","r",stdin);
42 freopen("changchun.out","w",stdout);
43 #endif
44 read(n);
45 pr[0]=1;
46 For(i,1,n) pr[i]=pr[i-1]*2%p;
47 For(i,2,n) {
48 int x,y;
49 read(x); read(y);
50 add(x,y);
51 }
52 dfs(1,0);
53 printf("%lld\n",(f[1][0]+f[1][1])%p);
54 Formylove;
55 }
樹dp
正解:
考慮點的聯通塊怎麼算,樹中砍掉k條邊就形成k+1個聯通塊,每條邊被砍的概率是1/2,那麼砍掉邊的期望就是(n-1)/2,形成聯通塊的期望就是(n-1)/2+1
然後邊的聯通塊就減去單獨一個點形成的聯通塊的個數的期望即可。
單獨點的聯通塊個數的期望等於每個點形成的單獨聯通塊的個數期望之和,即每個點成為單獨聯通塊的概率之和。llj切這題似乎只需要3min。
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=1000000007;
7 typedef long long LL;
8 typedef double db;
9 using namespace std;
10 int n,in[N];
11 LL pr[N],ans;
12
13 template<typename T> void read(T &x) {
14 char ch=getchar(); x=0; T f=1;
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<0?x+p:(x>=p?x-p:x); }
21
22 #define ANS
23 int main() {
24 #ifdef ANS
25 freopen("changchun.in","r",stdin);
26 freopen("changchun.out","w",stdout);
27 #endif
28 read(n);
29 pr[0]=1;
30 For(i,1,n) pr[i]=mo(pr[i-1]*2);
31 For(i,2,n) {
32 int x,y;
33 read(x); read(y);
34 in[x]++; in[y]++;
35 }
36 ans=((LL)n+1)*pr[n-1]%p;
37 For(i,1,n)
38 ans=mo(ans-pr[n-in[i]]);
39 printf("%lld\n",ans);
40 Formylove;
41 }
View Code
B 君的第二題 (harbin)
除了菜菜菜菜菜菜我不知道還能說些什麼。
弱智都知道的70pt做法就是隨便拿個啥子資料結構模擬,我不想打平衡樹又忘了樹狀陣列求第k大怎麼打,在那裡列印了一個樹狀陣列現場研究,還寫掛了一次。
正解是,考慮每個人是第幾輪被踢出去的,O(n)地dp這個東西,然後基數排序即可。。
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,mod=1e9+7;
7 typedef long long LL;
8 typedef double db;
9 using namespace std;
10 int T,n,k,pr[N],f[N],c[N],sa[N];
11
12 template<typename T> void read(T &x) {
13 char ch=getchar(); x=0; T f=1;
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 int p[N],bo[N];
20 void get_prime() {
21 For(i,2,1000007) {
22 if(!bo[i]) p[++p[0]]=i;
23 for(int j=1;j<=p[0]&&p[j]*i<=1000007;j++) {
24 bo[i*p[j]]=1;
25 if(i%p[j]==0) break;
26 }
27 }
28 }
29
30 void pre() {
31 int l=1,r=p[0],rs=1;
32 while(l<=r) {
33 int mid=((l+r)>>1);
34 if(p[mid]>=n) rs=mid,r=mid-1;
35 else l=mid+1;
36 }
37 int P=p[rs];
38 pr[0]=1;
39 For(i,1,n) pr[i]=(LL)pr[i-1]*P%mod;
40 }
41
42 LL mo(LL x) { return x>=mod?x-mod:x; }
43
44 #define ANS
45 int main() {
46 #ifdef ANS
47 freopen("harbin.in","r",stdin);
48 freopen("harbin.out","w",stdout);
49 #endif
50 pr[0]=1;
51 For(i,1,18) pr[i]=pr[i-1]*2;
52 get_prime();
53 read(T);
54 while(T--) {
55 read(n); read(k);
56 pre();
57 For(i,0,n-1) {
58 if(i%k==0) f[i]=0;
59 else f[i]=f[i-(i/k+1)]+1;
60 c[f[i]]++;
61 }
62 For(i,1,n-1) c[i]+=c[i-1];
63 Rep(i,n-1,0) sa[--c[f[i]]]=i;
64 LL ans=0;
65 For(i,0,n-1)
66 ans=mo(ans+(LL)sa[i]*pr[i]%mod);
67 printf("%lld\n",ans);
68 if(T) memset(c,0,sizeof(c));
69 }
70 Formylove;
71 }
View Code
B 君的第三題 (shenyang)
一個很弱智的狀壓dp,然而我當時竟然覺得一個質數跟自己互質,然後說這是什麼沙比題隨便搜一下就差不多了吧寫了個迭代加深。
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=107,up=65535;
7 typedef long long LL;
8 typedef double db;
9 using namespace std;
10 int p[20]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53};
11 int n,a[N],ans,f[N][up+7];
12
13 template<typename T> void read(T &x) {
14 char ch=getchar(); x=0; T f=1;
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 int get(int x) {
21 int rs=0;
22 For(i,0,15) if(x%p[i]==0)
23 rs|=(1<<i);
24 return rs;
25 }
26
27 #define ANS
28 int main() {
29 #ifdef ANS
30 freopen("shenyang.in","r",stdin);
31 freopen("shenyang.out","w",stdout);
32 #endif
33 read(n);
34 For(i,1,n) read(a[i]);
35 memset(f,127/3,sizeof(f));
36 f[0][0]=0;
37 ans=n*29;
38 For(i,1,n) {
39 For(x,1,53) {
40 int now=get(x),S=(now^up);
41 for(int s=S;;s=((s-1)&S)) {
42 f[i][s|now]=min(f[i][s|now],f[i-1][s]+abs(x-a[i]));
43 if(!s) break;
44 }
45 }
46 if(i==n) For(s,0,up) ans=min(ans,f[i][s]);
47 }
48 printf("%d\n",ans);
49 Formylove;
50 }
View Code