2020HDU多校第三场By Rynar 6791-6801
1001.Tokitsukaze, CSL and Palindrome Game
1002.Lady Layton and Stone Game
1003.Tokitsukaze and Colorful Tree
1004.Tokitsukaze and Multiple
const int N=1e5+10;
int n,p;
int a[N],s[N];
map<int,bool>q;
int main(){
int T;
cin>>T;
while (T--){
scanf("%d%d",&n,&p);
q.clear();
int cnt=0;
for (int i=1;i<=n;i++)scanf("%d",&a[i]);
s[0]=0;for (int i=1;i<=n;i++)s[i]=(s[i-1]+a[i])%p;
q[0]=1;
for (int i=1;i<=n;i++){
if (!q[s[i]])q[s[i]]=1;
else q.clear(),q[s[i]]=1,cnt++;
}
cout<<cnt<<endl;
}
return 0;
}
1005.Little W and Contest
思路

先算出总数,再每次相连时减去以上4种情况
const int mod=1e9+7;
const int N=2e6+10;
int n;
ll f[N],a[N],s1[N],s2[N];
int ff(int x){
if (f[x]==x)return x;
return f[x]=ff(f[x]);
}
int main(){
int T;
cin>>T;
while (T--){
scanf("%d",&n);
ll t1=0,t2=0;
for (int i=1;i<=n;i++){
scanf("%d",&a[i]);
if (a[i]==1)t1++,s1[i]=1,s2[i]=0;
else t2++,s2[i]=1,s1[i]=0;
f[i]=i;
}
ll ans;
if (t2<2)ans=0;
else if (t2==2)ans=t1;
else ans=t1*t2*(t2-1)/2+t2*(t2-1)*(t2-2)/6;
printf("%lld\n",ans%mod);
int x,y;
for (int i=1;i<n;i++){
scanf("%d%d",&x,&y);
int xx=ff(x),yy=ff(y);
if (xx!=yy){
ans-=s1[yy]*s2[xx]*(t2-s2[xx]-s2[yy]);
ans-=s1[xx]*s2[yy]*(t2-s2[xx]-s2[yy]);
ans-=s2[xx]*s2[yy]*(t2-s2[xx]-s2[yy]);
ans-=s2[xx]*s2[yy]*(t1-s1[xx]-s1[yy]);
f[xx]=yy;
s1[yy]+=s1[xx];s2[yy]+=s2[xx];
}
printf("%lld\n",ans%mod);
}
}
return 0;
}
1006.X Number
//280ms 假装数位dp的组合数问题
const int N=20+10;
ll n,l,r,d;
int num[N];
ll C[N][N],dp0[N];
map<array<int,10>,ll>dp[N][2][10];//f这一维可不要,因为state里面已经存了f的状态,不要运行速度稍慢一点,甚至记忆化也可不要,不过会慢3倍
array<int,10>state={0};
void get_C(int maxn){
C[0][0]=1;
for(int i=1;i<=maxn;i++){
C[i][0]=1;
for(int j=1;j<=i;j++){
C[i][j]=C[i-1][j]+C[i-1][j-1];
}
}
}
ll dfs(int n,bool f,bool lim){
if(!lim&&dp[n][f][d][state])return dp[n][f][d][state];
if (!n){
for (int i=0;i<10;i++){
if (i!=d&&state[i]>=state[d])return dp[n][f][d][state]=0;
}
return dp[n][f][d][state]=1;
}
ll ans=0;
if (!f&&!lim){//不为前导0且无上限限制时可以用dp处理后续数据,程序总复杂度为该段复杂度n^4*总长度18*d的个数*map的消耗时间,dp0[i]表示剩余i位前已经有的方案数
for (int i=0;i<=n;i++){
for (int j=0;j<=n-i;j++)dp0[j]=0;
dp0[n-i]=C[n][i];
for (int j=0;j<10;j++){//类似背包的做法,枚举每个值
if (j==d)continue;
if (state[d]+i<=state[j]){
dp0[0]=0;break;
}
for (int k=0;k<=n-i;k++){
for (int p=1;p<=min(k,state[d]+i-state[j]-1);p++){//能放几个
dp0[k-p]+=dp0[k]*C[k][p];
}
}
}
ans+=dp0[0];
}
return dp[n][f][d][state]=ans;
}
//以下耗时较小
int up=lim?num[n]:9;
for (int i=0;i<=up;i++){//f记录是否是前导0
if (f&&i==0)ans+=dfs(n-1,f&&(i==0),lim&&(i==up));
else{
if (i==d||state[i]+1<state[d]+n-1){
state[i]++;
ans+=dfs(n-1,f&&(i==0),lim&&(i==up));
state[i]--;
}
}
}
if (!lim)dp[n][f][d][state]=ans;
return ans;
}
ll solve(ll x){
int cnt=0;
while (x){
num[++cnt]=x%10;x/=10;
}
return dfs(cnt,1,1);
}
int main(){
int T;
get_C(20);
scanf("%d",&T);
while (T--){
scanf("%lld%lld%lld",&l,&r,&d);
printf("%lld\n",solve(r)-solve(l-1));
}
return 0;
}
1007.Tokitsukaze and Rescue
思路:直接k^2,对当前的最短路枚举删除一条边,重新搜最短路,重复k次
typedef pair<int,int>P;
const int inf=0x3f3f3f3f;
const int N=50+10;
int n,k,mx;
int mp[N][N],c[N];
int pre[N][N];
void dijkstra(int x,int id){
priority_queue< P , vector<P> , greater<P> > q;
fill(c,c+n+1,inf);
c[x]=0;pre[1][id]=1;
q.push({0,x});
while(!q.empty()){
P r=q.top();
q.pop();
int u=r.second;
if (c[u]<r.first)continue;
for (int to=1;to<=n;to++){
int d=mp[u][to];
if(c[u]+d<c[to]){
c[to]=c[u]+d;
pre[to][id]=u;
q.push({c[to],to});
}
}
}
}
void solve(int x){
if (x==0){
mx=max(mx,c[n]);
return;
}
dijkstra(1,x);
int p=n;
while (pre[p][x]!=p){
int t=mp[p][pre[p][x]];
mp[p][pre[p][x]]=mp[pre[p][x]][p]=inf;
solve(x-1);
mp[p][pre[p][x]]=mp[pre[p][x]][p]=t;
p=pre[p][x];
}
}
int main(){
int T;
int x,y;
scanf("%d",&T);
while (T--){
scanf("%d%d",&n,&k);
for (int i=1;i<=n*(n-1)/2;i++){
scanf("%d%d",&x,&y);
scanf("%d",&mp[x][y]);
mp[y][x]=mp[x][y];
}
mx=0;
solve(k+1);
printf("%d\n",mx);
}
return 0;
}
1008.Triangle Collision
思路:

碰撞次数就是途经边数,分平行x轴的边,60度的边,-60度的边计算碰撞次数
const double eps=1e-8;
int L,x,y,vx,vy,k;
double h,p;
ll check(double t){
ll ans=0;
double xx=t*vx+x,yy=t*vy+y;
if (yy>0)ans+=yy/h;
if (yy<0)ans+=-yy/h+1;
double y1=yy/2-xx*p+h/2;//坐标系逆时针旋转60度
if (y1>0)ans+=y1/h;
if (y1<0)ans+=-y1/h+1;
y1=yy/2+xx*p+h/2;//坐标系顺时针旋转60度
if (y1>0)ans+=y1/h;
if (y1<0)ans+=-y1/h+1;
return ans;
}
int main(){
int T;
scanf("%d",&T);
while (T--){
scanf("%d%d%d%d%d%d",&L,&x,&y,&vx,&vy,&k);
h=sqrt(3)*L/2;
p=sqrt(3)/2;
double l=0,r=1e12;
while (l+eps<r){
double mid=(l+r)/2;
if (check(mid)>=k)r=mid;
else l=mid;
}
printf("%.8lf\n",r);
}
return 0;
}
1009.Parentheses Matching
const int N=1e5+10;
int n,p;
char s[N];
int main(){
int T;
cin>>T;
while (T--){
scanf("%s",s);
int len=strlen(s),h=0,p=0,cnt=0;
bool f=0;
for (int i=0;i<len;i++){
if (s[i]=='*')p++;
if (s[i]=='(')h++;
if (s[i]==')')h--;
if (h<0){
if (p)h++,cnt++,p--;
else{
f=1;break;
}
}
}
for (int i=0;i<len;i++){
if (cnt&&s[i]=='*')s[i]='(',cnt--;
}
cnt=0,p=0,h=0;
for (int i=len-1;i>=0;i--){
if (s[i]=='*')p++;
if (s[i]=='(')h--;
if (s[i]==')')h++;
if (h<0){
if (p)h++,cnt++,p--;
else{
f=1;break;
}
}
}
for (int i=len-1;i>=0;i--){
if (cnt&&s[i]=='*')s[i]=')',cnt--;
}
if (f)printf("No solution!\n");
else{
for (int i=0;i<len;i++){
if (s[i]!='*')printf("%c",s[i]);
}
puts("");
}
}
return 0;
}
1010.Play osu! on Your Tablet
1011.Game on a Circle
禁止类似码农教程的网站爬取,抄袭博客内容。
https://www.cnblogs.com/rair/

浙公网安备 33010602011771号