马猴烧酒

题意:懂得都懂

思路:由于n的范围很小,直接爆搜枚举一下a放到第几行,然后当枚举到a次的时候,判断一下需要几次b操作

代码:

#include<bits/stdc++.h>
using namespace std;
int const N=1e4+5;
#define int long long
void solve(){
    int n,m,a,b;
    cin>>n>>m>>a>>b;
    vector<vector<char>>mp(n+1,vector<char>(m+1));
    vector<bool>vis(n+1,false);
    bool  st=0;
    for (int i = 1; i <=n ; ++i) {
        for (int j = 1; j <=m ; ++j) {
            cin>>mp[i][j];
        }
    }
    function<void (int)>dfs=[&](int cnt){
        if(st)return ;
        if(cnt==a){
            int ct=0;
            for (int i = 1; i <=m ; ++i) {
                for (int j = 1; j <=n ; ++j) {
                    if(!vis[j]&&mp[j][i]=='*'){
                        ct++;
                        break;
                    }
                }
            }
            if(ct<=b){
                st=1;
                return ;
            }
        }
        else{
            for (int i = 1; i <=n ; ++i) {
                if(!vis[i]){
                    vis[i]=1;
                    dfs(cnt+1);
                    vis[i]=0;
                }
            }
        }
    };
    dfs(0);
    if(st){
        cout<<"yes\n";
    }
    else{
        cout<<"no\n";
    }
}
signed main(){
    ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
    int t;
    cin>>t;
    while(t--){
        solve();
    }

}

阶乘

题意:懂得都懂

思路:我们找出p的质因子和个数,然后我们知道n越大就越可能是p的倍数,二分答案,我们可以求出当前的mid的阶乘mid!能够分成几个p的第i个质因子,然后我们判断是否≥我们所需要的i.second,由于质因子之间相互独立,因此我们检验质因子a的时候,对b无影响,因此检验完之后恢复mid值检验下一个即可

代码:

#include<bits/stdc++.h>
using namespace std;
int const N=1e4+5;
#define int long long
void solve(){
    int n;
    unordered_map<int,int>has;
    int x;
    cin>>x;
    int p=x;
    for (int i = 2; i <=x/i ; ++i) {
        while (x%i==0){
            has[i]++;
            x/=i;
        }
    }
    if(x>1)
        has[x]++;
    auto  check=[&](int mid){
        for (auto i:has) {
            int y=mid;
            int cnt=0;
            while(y){
                cnt+=y/i.first;
                y/=i.first;
            }
            if(cnt<i.second)return false;
        }
        return true;

    };
    int l=1,r=p;
    int ans=-1;
    while(l<=r){
        int mid=l+r>>1;
        if(check(mid)){
            r=mid-1;
            ans=mid;
        }
        else{
            l=mid+1;
        }
    }
    cout<<ans<<endl;

}
signed main(){
    ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
    int t;
    cin>>t;
    while(t--){
        solve();
    }

}

完全图

题意:给一个n个点的图,每个点都与其他任何点相连,即每个点n-1条边,问如果可以删除m条边,这个图最多分成几个连通块

思路:我们新增加一个连通块需要删除n-1条边,第二个需要n-2,因此我们可以推出新增加最多的n-1个连通块,需要删1+2+3+4+n-1条边,因此我们可以二分答案,问新增加mid个连通块需要删除几条边,即可,要开__int128

代码:

#include<bits/stdc++.h>
using namespace std;
#define  int __int128
int read()
{
    int res=0;
    char scan[1005];
    scanf("%s",scan);
    for(int i=0;i<strlen(scan);i++)
        res*=10,res+=scan[i]-'0';
    return res;
}
signed main(){
    int t;
    t=read();
    while(t--){
        int a,b;
        a=read(),b=read();
        __int128 n,m;
        n=a,m=b;
        __int128 l=0,r=n-1;
        if(m>=(n-1)*n/2){
            cout<<(long long)a<<"\n";
        }
        else{
            __int128 x=n-1;
            auto check=[&](__int128 mid){
                __int128 res=(n-mid)-1;
                res=x*(x+1)/2-res*(res+1)/2;
                return res<=m;
            };

            int ans=0;
            while(l<=r){
                int mid=l+r>>1;

                if(check(mid)){
                    ans=mid;
                    l=mid+1;
                }
                else{
                    r=mid-1;
                }
            }
            ans+=1;
            cout<<(long long)ans<<endl;
        }

    }
}

树上求和

题意:给一个n个点,n-1条边的树,我们为每一条边赋值(1到n-1),每一条边只能赋值一种,问到任意点到任意点的权值之和最小是多少,比如样例之中,到4的点有3个,因此w4的权值是3 1 2,3-1这条边,2的左边有两个点,右子树有2个点(包括自己),因此这条边的w就是1 2 2=4

思路:我们可以知道一个边的贡献是左边的点的个数 右边点的个数再乘权值,因此我们根据点的乘积来排序,然后最大的乘最小边权,即可,我们处理点的乘积时,可以通过dfs寻早点,比如从3开始搜,到右边最底部为3个点,那么左边就是4-3,一个点。然后就是3 1;

代码:

#include<bits/stdc++.h>
using namespace std;
#define PII pair<int,int>
#define int long long
void solve(){
     int n;
     cin>>n;
     vector<int>q[n+1];
    for (int i = 1; i <n ; ++i) {
        int a,b;
        cin>>a>>b;
        q[a].push_back(b);
        q[b].push_back(a);
    }
    vector<int>ans;
    function <int  (int,int)>dfs=[&](int u,int v){
        int sum=1;
        for (int i = 0; i <q[u].size() ; ++i) {
            if(q[u][i]!=v){
                sum+=dfs(q[u][i],u);
            }
        }
        ans.push_back(sum*(n-sum));
        return sum;
    };
    dfs(1,-1);
    int res=0;
    int l=n-1;
    sort(ans.begin(),ans.end());
    for (int i = 1; i <ans.size() ; ++i) {
        res+=(ans[i]*l);
        l--;
    }
    cout<<res<<endl;
    return;

}
signed main(){
    int t=1;

    while (t--){
        solve();
    }

}
posted on 2023-07-20 12:20  IR101  阅读(6)  评论(0编辑  收藏  举报  来源