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; } int main(){ 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最优子空间都是已知的,于是描述一下就可以。
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; }