wxy 3.31 牛客练习赛60重现
作者:互联网
v>
wxy 3.31 牛客练习赛60重现 5075 A 看到位运算,可以往二进制方面去想,可以把1-n所有的的每位放到相应的位置上,然后遍历所有的 数,每次都把他拆分成二进制和刚刚统计的那些数的每位进行与运算 C DP 设dp[ i ] [ j ]表示前i个,长度为j的本质不同的子序列有多少,那么dp[ i ] [ j ]=dp[ i - 1] [ j - 1 ]+dp[ i - 1] [ j ],但是会有重复,要减去前面的 dp [ pos[ s[ i ] ] ] [ j -1 ] 然后初始化, i:0-n dp[ i ] [ 0 ]=1 选0个的宣发为1,就是什么都不选 dp考虑如何转移,如何从前一步到当前步,dp[ i ] [ j ] = dp [ i - 1 ] [ j ] + dp[ i - 1 ] [ j - 1 ]一般当前步有 两种选择,选择当前这一个或者不选择当前这一个。每多一个有可能会和前面有重复,重复部分一般是 和当前位置相同的位置。 D 数据出水了。。。用比赛时候的做法是会TLE,但是如果比赛的时候有很多人过了的题,莽一发没有关 系,T了不亏 真正的做法是同余最短路 get到新姿势 # include <bits/stdc++.h> using namespace std; typedef long long LL; const LL mod=1e9+7; const int MAXN=1e3+100; char s[MAXN]; int pos[30],dp[MAXN][MAXN]; int main() { LL n,k; scanf("%lld%lld",&n,&k); scanf("%s",s+1); dp[0][0]=1; for(int i=1;i<=n;++i){ dp[i][0]=1; for(int j=1;j<=k;++j){ dp[i][j]=dp[i-1][j-1]+dp[i-1][j]; if(pos[s[i]-'a']) dp[i][j]-=dp[pos[s[i]-'a']-1][j-1]; dp[i][j]=(dp[i][j]%mod+mod)%mod; } pos[s[i]-'a']=i; } printf("%d",dp[n][k]); return 0; }E 长链剖分 待补 # include <bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<int,int> pii; const int MAXN=1e5+100; const int INF=0x7fffffff; LL dis[MAXN]; LL ans[10]; LL a,b,c,k; pii edge[MAXN]; void dij() { for(int i=1;i<=c;++i) dis[i]=INF; priority_queue<pii,vector<pii>,greater<pii> > q; q.push(pii(0,0)); while(!q.empty()){ pii x=q.top(); q.pop(); int u=x.first,v=x.second; if(dis[(v+a)%c]>dis[v]+a){ dis[(v+a)%c]=dis[v]+a; edge[(v+a)%c]=pii(v,1); q.push(pii(dis[(v+a)%c],(v+a)%c)); } if(dis[(v+b)%c]>dis[v]+b){ dis[(v+b)%c]=dis[v]+b; edge[(v+b)%c]=pii(v,2); q.push(pii(dis[(v+b)%c],(v+b)%c)); } } return ; } void dfs(LL now) { if(now==0) return ; ans[edge[now].second]++; dfs(edge[now].first); return ; } int main() { scanf("%lld%lld%lld%lld",&a,&b,&c,&k); dij(); dfs(k%c); ans[3]=(k-a*ans[1]-b*ans[2])/c; printf("%lld %lld %lld\n",ans[1],ans[2],ans[3]); return 0; }标签:pii,练习赛,int,LL,wxy,60,ans,dp,dis 来源: https://www.cnblogs.com/fengzlj/p/15941295.html