8.13訓練
阿新 • • 發佈:2020-08-14
https://ac.nowcoder.com/acm/contest/7055
B-Icebound and Squence
思路:本來以為是用等比數列求和公式做的,結果做不出來,隊友用的遞迴吧算是,和一個奇怪的公式
AC程式碼:
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; typedef long long ll; ll quick(ll q,ll n,ll p){ ll ans=1,base=q; while(n){ if(n&1) ans=ans*base%p; base=base*base%p; n>>=1; } return ans; } ll solve(ll q,ll n,ll p){ if(n==1) return q%p; else if(n%2==0) return (solve(q,n/2,p)+quick(q,n/2,p)*solve(q,n/2,p))%p; else return (solve(q,n/2,p)+quick(q,n/2,p)*solve(q,n/2,p)+quick(q,n,p))%p; } intmain(){ int t; cin>>t; while(t--){ ll q,n,p; cin>>q>>n>>p; cout<<solve(q,n,p)%p<<endl; } return 0; }
C-分治
題面是漢語,也不難理解,就不說了。
思路:這道題看到感覺可以小區間推大區間,就用的區間dp.
狀態轉移方程:
if(k==j) dp[j][i+j-1]=min(dp[j][i+j-1],a[k]*(i-1)+dp[j+1][i+j-1]); else if(k==j+i-1) dp[j][i+j-1]=min(dp[j][i+j-1],a[k]*(i-1)+dp[j][i+j-2]); else dp[j][i+j-1]=min(dp[j][i+j-1],dp[j][k-1]+dp[k+1][i+j-1]+(i-1)*a[k]);//怕錯,分的比較細
其實就是j到i+j-1這個區間的時候,你需要暴力列舉假設從k處分開,而且小於距離i最優子空間都是已知的,於是描述一下就可以。
感受:思路其實已經有了,但是中間因為看錯題,改了老半天,不過只已經可以訓練中做出來這種dp題了(因為不會分治)
最後就是它和之前的石子合併很像
AC程式碼:
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; typedef long long ll; ll a[3100],dp[2100][2100]; int main(){ int t; cin>>t; while(t--){ int n; cin>>n; memset(dp,0x3f3f3f3f,sizeof(dp)); for(int i=1;i<=n;i++){ cin>>a[i]; } for(int i=1;i<=n;i++) dp[i][i]=0; for(int i=2;i<=n;i++){ for(int j=1;j<=n-i+1;j++){ for(int k=j;k<=j+i-1;k++){ if(k==j) dp[j][i+j-1]=min(dp[j][i+j-1],a[k]*(i-1)+dp[j+1][i+j-1]); else if(k==j+i-1) dp[j][i+j-1]=min(dp[j][i+j-1],a[k]*(i-1)+dp[j][i+j-2]); else dp[j][i+j-1]=min(dp[j][i+j-1],dp[j][k-1]+dp[k+1][i+j-1]+(i-1)*a[k]); } } } cout<<dp[1][n]<<endl; } }
L-smart robot
思路:一道搜尋的題目,不過你得知道搜到幾位數就行,xx學長給了個式子:10^k<n*n*4^k(k表示深度)然後直接搜就行。
AC程式碼:
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; const int M=1e6+2; int s[2100][2100],vis[2200000],n; int dx[4]={0,0,1,-1}; int dy[4]={1,-1,0,0}; void dfs(int x,int y,int num,int step){ if(step>=6) return ; vis[num]=1; for(int i=0;i<4;i++){ int fx=x+dx[i]; int fy=y+dy[i]; if(fx<=n&&fx>=1&&fy>=1&&fy<=n){ dfs(fx,fy,num*10+s[fx][fy],step+1); } } return ; } int main(){ cin>>n; for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ cin>>s[i][j]; } } for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ dfs(i,j,s[i][j],0); } } for(int i=0;i<=M;i++){ if(!vis[i]){ cout<<i<<endl; break; } } return 0; }
J-舔狗
思路:由於邊數只有一個環,從入度較少的點慢慢往前更新刪除,就算拆了環也沒有關係。
感受:自己程式碼能力不強,只能去靠隊友,欸,補的題。
AC程式碼:
#include<iostream> #include<cstdio> #include<algorithm> #include<queue> #include<cstring> using namespace std; const int M=1e6+5; int x,n,a[M],vis[M],in[M]; struct node{ int u,v;//u為編號,v為入度 bool friend operator<(node x,node y){ return x.v>y.v; } }; void solve(){ int ans=0; priority_queue<node>q; for(int i=1;i<=n;i++){ q.push(node{i,in[i]}); } while(!q.empty()){ node cur=q.top();q.pop(); if(vis[a[cur.u]]||vis[cur.u]) continue; ans+=2; vis[cur.u]=1; vis[a[cur.u]]=1; q.push(node{a[a[cur.u]],--in[a[a[cur.u]]]}); } cout<<n-ans<<endl; } int main(){ cin>>n; for(int i=1;i<=n;i++){ cin>>a[i]; in[a[i]]++; } solve(); return 0; }