• 4.9cf自训9..


    cf401D 状态压缩dp好题,每次把新加入集合的数字放在最后即可

    /*
    它可以通过重新排列数字n,
    它没有任何前导零,
    x除以m后的余数等于0. 
    
    每次把新加的数放在最后 
    dp[i][j]表示状态i下模m=j的数量 
    dp[i|(1<<k)][j*10+a[k]]+=dp[i][j];
    
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    ll len,n,m,a[20];
    ll dp[1<<19][100];
    int main(){
        cin>>n>>m;
        while(n)a[++len]=n%10,n/=10;
        dp[0][0]=1;
        for(int i=0;i<(1<<len)-1;i++)
            for(int j=0;j<m;j++)
                for(int k=0;k<len;k++){
                    if(i&(1<<k))continue;
                    if(i==0&&a[k+1]==0)continue;//前导0 
                    dp[i|(1<<k)][(j*10+a[k+1])%m]+=dp[i][j];
                }
        ll cnt[10]={},f[20]={},ans=dp[(1<<len)-1][0];
        f[0]=f[1]=1;
        for(int i=2;i<=18;i++)f[i]=f[i-1]*i;
        for(int i=1;i<=len;i++)cnt[a[i]]++;
        for(int i=0;i<10;i++)
            if(cnt[i])ans/=f[cnt[i]];
        cout<<ans<<endl;    
    }
    View Code

    cf959E 思维题

    #include<bits/stdc++.h> 
    using namespace std;
    #define ll long long
    ll n,ans;
    ll lowbit(ll x){return x&(-x);} 
    
    int main(){
        cin>>n;
        ll tmp=n,cnt=1;
        while(tmp){
            ans+=tmp/2*cnt;
            tmp/=2,cnt*=2;
        }
        if(n==lowbit(n)){
            cout<<ans<<endl;
            return 0;
        }
        while(n){
            n-=lowbit(n);    ans+=lowbit(n);
        }
        cout<<ans<<endl;return 0;
    }
    View Code

    cf598E dp好题,就是最经典的线性dp,想通了挺简单的

    /*
    dp[i][j][k]在i*j的方块里吃k大小的代价 
    */
    #include<bits/stdc++.h>
    using namespace std;
    int dp[31][31][51];
    int main(){
        for(int i=0;i<=30;i++)
            for(int j=0;j<=30;j++)    
                for(int k=0;k<=50;k++){
                    if(k==0 || k==i*j){
                        dp[i][j][k]=0;
                        continue;
                    }
                    else dp[i][j][k]=100000000;
                    for (int h = 0; h <= k; h++){
                        for (int m = 1; m < j; m++)
                            dp[i][j][k] = min(dp[i][j][k], dp[i][m][h] + dp[i][j - m][k - h] + i*i);
                        for (int m = 1; m < i; m++)
                            dp[i][j][k] = min(dp[i][j][k], dp[m][j][h] + dp[i - m][j][k - h] + j*j);
                    }
                }
        int t,n,m,k;
        cin>>t;
        while(t--){
            cin>>n>>m>>k;
            cout<<dp[n][m][k]<<endl;
        } 
    }
    View Code

    cf886D 字符串乱搞+判环

    #include<iostream>
    #include<algorithm>
    #include<string>
    #include<string.h>
    using namespace std;
     
    string s,ans[28];
     
    int main()
    {
        int i,j,n,f,x,len;
        int vis[28],chu[28],ru[28],mp[28][28];    
        while(cin>>n)
        {
            f=1;
            memset(mp,0,sizeof(mp));    //字符构成的图 
            memset(ru,-1,sizeof(ru));    //每个字符的入度 
            memset(chu,-1,sizeof(chu));    //每个字符的出度 
            //在下面这个循环中,chu/ru=0则说明字符出现过,chu/ru=-1则没出现过 
            for(i=0;i<n;i++)
            {
                cin>>s; //输入字符串 
                memset(vis,0,sizeof(vis)); //用于判断每个字符串中字符出现的次数 
                len=s.length();
                vis[s[0]-'a']++; //首个字符出现次数+1 
                ru[s[0]-'a']=0;  //首个字符出现过 
                chu[s[0]-'a']=0; //首个字符出现过
                for(j=1;j<len;j++)
                { //从第 1 个字符开始建图 
                    int u=s[j-1]-'a'; //前一字符 
                    int v=s[j]-'a';   //当前字符 
                    mp[u][v]=1;
                    vis[v]++;
                    if(vis[v]>1) f=0; //如果出现次数>1,则输出 NO 
                    ru[v]=0;
                    chu[v]=0;
                }
            }
            int next[28]; //每个字符的后继字符 
            memset(next,-1,sizeof(next));
            for(i=0;i<26;i++)
                for(j=0;j<26;j++)
                    if(mp[i][j])
                    { //如果存在边                 
                        ru[j]++;  //入度+1 
                        chu[i]++; //出度+1 
                        next[i]=j; //记录后继 
                    }
            for(i=0;i<26;i++)
                if(ru[i]>1||chu[i]>1)
                { //如果有字符的出度或入度 >1则输出 NO 
                    f=0;                
                    break;
                }
            for(i=0;i<26;i++)
            { //判断是否有环 
                x=i;
                memset(vis,0,sizeof(vis));
                while(x!=next[x])
                {
                    if(vis[x]==1)
                    { //如果当前元素访问过则有环 
                        f=0;
                        break;
                    }
                    vis[x]=1;
                    x=next[x];
                }
            }
            if(n>351 || !f)
            {
                cout<<"NO"<<endl;
                continue;
            }
            int tol=0;
            for(i=0;i<26;i++) //遍历 26个字符 
                if(ru[i]==0)
                { //如果入度为 0,则会形成一串字符 
                    ans[tol]='a'+i;
                    x=i;
                    while(next[x]!=-1)
                    { //加入后继字符 
                        char c=next[x]+'a';
                        ans[tol]+=c;
                        x=next[x];
                    }
                    tol++;
                }
            sort(ans,ans+tol); //排序    
            for(i=0;i<tol;i++) cout<<ans[i];
            cout<<endl;
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Linux-redis实现session复制
    Linux-sentinel实现redis主从高可用
    Linux-初识redis
    Docker-docker-machine
    Linux-Nginx服务调优(下)
    Linux-Nginx服务调优(上)
    Linux-nginx.conf配置文件模板
    Linux-编译安装Nginx
    VS Code (visual studio code) VSC 编辑器(微软出品,js开发的编辑器)
    好用的在线工具
  • 原文地址:https://www.cnblogs.com/zsben991126/p/10680320.html
Copyright © 2020-2023  润新知