ATP學姐的模擬賽
阿新 • • 發佈:2018-10-04
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> 4T1# 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 }
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學姐的模擬賽