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

posted @ 2020-07-28 19:01  Rynar  阅读(458)  评论(0)    收藏  举报