1. 程式人生 > >ATP學姐的模擬賽

ATP學姐的模擬賽

opened close continue -- int key ems set read

  T1:求所有的$n$位數中有幾個數滿足:每一位要麽是$A$要麽是$B$,並且這個$n$位數的每一位加起來是$A$或$B$的倍數。

  $n<=100000,0<A,B<=9$且$A$與$B$不相等

  因為昨天剛講了數位$dp$,理所當然的就往那方面去想了.其實用組合數學也可以做,而且還比較簡短.

  用$f[i][j][k]$表示目前填到第$i$位,對$a$取模余數為$j$,對$b$取模余數為$k$的方案數.滾動數組,空間可以壓得非常小.

  技術分享圖片
 1 # include <cstdio>
 2 # include <iostream>
 3 # include <cstring>
 4
# include <string> 5 # define R register int 6 # define mod 1000000007 7 8 using namespace std; 9 10 const int maxn=100005; 11 int dp[3][10][10]; 12 int a,b,n,ans,no,nex; 13 14 inline int ad (int a,int b) { a=a+b; if(a>=mod) a-=mod; return a; } 15 16 int solve () 17 { 18 dp[0][0][0]=1; 19 for
(R i=0;i<n;++i) 20 { 21 no=i&1; 22 nex=no^1; 23 memset(dp[nex],0,sizeof(dp[nex])); 24 for (R m1=0;m1<a;++m1) 25 for (R m2=0;m2<b;++m2) 26 { 27 if(!dp[no][m1][m2]) continue; 28 dp[nex][m1][(m2+a)%b]=ad(dp[no][m1][m2],dp[nex][m1][(m2+a)%b]);
29 dp[nex][(m1+b)%a][m2]=ad(dp[no][m1][m2],dp[nex][(m1+b)%a][m2]); 30 } 31 } 32 int ans=0; 33 for (R m1=0;m1<a;++m1) 34 for (R m2=0;m2<b;++m2) 35 if(m1==0||m2==0) ans=ad(ans,dp[n&1][m1][m2]); 36 return ans; 37 } 38 39 int main() 40 { 41 scanf("%d%d%d",&n,&a,&b); 42 printf("%d",solve()); 43 return 0; 44 }
T1

  T2:求逆序對數量*360。沒了。 

  技術分享圖片
 1 # include <cstdio>
 2 # include <iostream>
 3 # include <cstring>
 4 # include <string>
 5 # include <algorithm>
 6 # define R register int
 7 # define lowbit(i) (i&(-i))
 8 # define mod 1000000007
 9 
10 using namespace std;
11 
12 const int maxn=500005;
13 struct nod
14 {
15     int key,val;
16 }a[maxn];
17 int n,v[maxn];
18 int t[maxn],ans,cnt;
19 
20 bool cmp (nod a,nod b) { return a.val<b.val; }
21 
22 void add (int pos,int val)
23 {
24     for (R i=pos;i<=cnt;i+=lowbit(i)) t[i]+=val;
25 }
26 
27 int ask (int pos)
28 {
29     int ans=0;
30     for (R i=pos;i;i-=lowbit(i)) ans+=t[i];
31     return ans;     
32 }
33 
34 int main()
35 {
36     scanf("%d",&n);
37     for (R i=1;i<=n;++i)
38         scanf("%d",&a[i].val),a[i].key=i;
39     sort(a+1,a+1+n,cmp);
40     a[0].val=a[1].val+1;
41     for (R i=1;i<=n;++i)
42     {
43         if(a[i].val!=a[i-1].val) ++cnt;
44         v[ a[i].key ]=cnt;
45     }
46     for (R i=1;i<=n;++i)
47     {
48         ans+=ask(cnt)-ask(v[i]);
49         if(ans>=mod) ans-=mod;
50         add(v[i],1);    
51     }
52     ans=(long long)ans*360%mod;
53     printf("%d",ans);
54     return 0;
55 }
T2

  T3:給定一棵正邊權的樹,求離每個點最遠的點有多遠;

  有一個定理:離每個點最遠的點必然是直徑端點上的一點,不過...我不是這麽做的。

  以任意點為端點的最長路要麽在它的子樹裏面,要麽是從父親走過來的,經典的$up and down$題目.註意,父親的最長路有可能本來就是從自己這裏走過去的,再用父親來更新就會走重復的路徑了.那怎麽辦呢?再記錄一條次長路徑即可,細節什麽的...自己想吧。 

  技術分享圖片
 1 # include <cstdio>
 2 # include <iostream>
 3 # include <cstring>
 4 # include <string>
 5 # define R register int
 6 
 7 using namespace std;
 8 
 9 const int maxn=1000006;
10 int n,h,x,y,co,firs[maxn],dep[maxn],m1[maxn],m2[maxn];
11 struct edge
12 {
13     int too,nex,co;
14 }g[maxn<<1];
15 
16 int read()
17 {
18     int x=0,f=1;
19     char c=getchar();
20     while (!isdigit(c)) { if(c==-) f=-f; c=getchar(); }
21     while (isdigit(c)) { x=(x<<3)+(x<<1)+(c^48); c=getchar(); }
22     return x*f;
23 }
24 
25 void add (int x,int y,int co)
26 {
27     g[++h].too=y;
28     g[h].co=co;
29     g[h].nex=firs[x];
30     firs[x]=h;
31 }
32 
33 void upp (int x)
34 {
35     int j,len;
36     for (R i=firs[x];i;i=g[i].nex)
37     {
38         j=g[i].too;
39         if(dep[j]) continue;
40         dep[j]=dep[x]+1;
41         upp(j);
42         len=m1[j]+g[i].co;
43         if(len>m1[x]) m2[x]=m1[x],m1[x]=len;
44         else if(len==m1[x]) m2[x]=len;
45         else m2[x]=max(m2[x],len);
46     }
47 }
48 
49 void dowwn (int x)
50 {
51     int j,len;
52     for (R i=firs[x];i;i=g[i].nex)
53     {
54         j=g[i].too;
55         if(dep[j]<dep[x]) continue;
56         len=m1[x];
57         if(len==m1[j]+g[i].co) len=m2[x];
58         len+=g[i].co;
59         if(len>m1[j]) m1[j]=len;
60         else if(len==m1[j]) m2[j]=len;
61         else m2[j]=max(m2[j],len);
62         dowwn(j);
63     }
64 }
65 
66 int main()
67 {
68     n=read();
69     for (R i=1;i<n;++i)
70     {
71         x=read(),y=read(),co=read();
72         add(x,y,co);
73         add(y,x,co);
74     }
75     dep[1]=1;
76     upp(1);
77     dowwn(1);
78     for (R i=1;i<n;++i)
79         printf("%d ",m1[i]);
80     printf("%d",m1[n]);
81     return 0;
82 }
T3

  T4:帶修改動態逆序對。

  $n$為序列長度,$m$為修改次數.

  技術分享圖片

  這題好啊,不用寫代碼,只需要寫一個做法的$txt$,學姐看做法給分qwq.正好是只會說不會寫.

  技術分享圖片

  這個做法竟然被給了滿分QAQ

  ---shzr

ATP學姐的模擬賽