• 牛客小白月赛23


    链接:https://ac.nowcoder.com/acm/contest/4784#question
    B 最小的n,是n!=p的倍数
    从质因数的角度找,找到出现每个质因数的次数的最小的数再取max,假设质因数p出现了m次,p只会出现在p的倍数里面,p出现一次,p*2又出现一次,依次类推,特殊的n^2出现2次, n ^3出现3次…
    1还需要特判

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=5010;
    #define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tir(0);
    int n,t;
    int get(int x,int cnt)//找x出现cnt次的那个最小值
    {
    	int i=x,res=0;
    	while(1)
    	{
    		int t=i;
    		while(t%x==0) t/=x,res++;
    		if(res>=cnt) return i;
    		i+=x;
    	}
    }
    int main()
    {
    	cin>>t;
    	while(t--)
    	{
    		cin>>n;
            if(n==1) 
            {
                cout<<1<<endl;
                continue;
            }
    		int k=0,num[1000]={0};
    		map<int,int> mp;
    		for(int i=2;i<=n/i;i++)
    		{
    			if(n%i==0) num[k++]=i;
    			while(n%i==0)
    			{
    				mp[i]++;
    				n/=i;
    			}
    		}
    		if(n>1) num[k++]=n,mp[n]++;
    		int ans=0;
    		for(int i=0;i<k;i++)
    			ans=max(ans,get(num[i],mp[num[i]]));
    		cout<<ans<<endl;
    	}
    	return 0;
    }
     
    

    C 完全图每条边连n-1条边,wtm以为有n条,裂开。那么新出现一个连通块最少需要删n-1条边(将一个点完全割出来),两个就是n-1+n-2(割去一个点后,那个大的连通块剩n-1个点),m个就是
    (n-1)+(n-2)+…+(n-m)=m+(n-1+n-m),找到这个规律后就可以二分了。数据范围1e18,会爆ll,可以用int128,也可以用python

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=5010;
    #define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tir(0);
    ll n,t,m;
    void print(__int128 x) 
    { 
        if(!x) 
        { 
            puts("0"); 
            return ; 
        } 
        string ret=""; 
        while(x) 
        { 
            ret+=x%10+'0'; 
            x/=10; 
        } 
        reverse(ret.begin(),ret.end()); 
        cout<<ret<<endl; 
    }
    int main()
    {
        cin>>t;
        while(t--)
        {
            cin>>n>>m;
            __int128 l=0,r=n;
            while(l<r)//二分新增连通块的数量
            {
                __int128 mid = l+r >> 1;
                if((mid*(2*n-mid-1)/2)>m) r=mid;
                else l=mid+1;
            }
            print(r);//二分出不满足的最小值,答案就是l-1+1
        }
        return 0;
    }
    

    E 32为有符号整数的范围是(-2^31, 2 ^31-1)共有2 ^32个数,对于任意一个数a都存在一个数c-b在int范围内,因为会溢出,所以答案就是2 ^32

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=100010,inf=0x3f3f3f3f;
    #define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tir(0);
    int n,a[N],l=-inf,r=inf;
    int main()
    {
    	cin>>n;
    	cout<<(1ll<<32);
    	return 0;
    }
    

    G 需要处理每一条边的贡献,然后按贡献从大到小赋值从小到大,每一条边的贡献是有多少路径(u,v)经过这条边,因为是一棵树,所以任意两点间路径唯一,那么贡献是多少呢,就是这条边两边的点数量的乘积,边两边任意两点一定会经过这条边,之前做过类似的可是给忘了…

    #include<bits/stdc++.h>
    using namespace std;
    const int N=200010;
    #define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int n,h[N],e[N],ne[N],idx;
    vector<long long> ve;
    void add(int a,int b)
    {
    	e[idx]=b;
    	ne[idx]=h[a];
    	h[a]=idx++;
    }
    int dfs(int u,int pre)
    {
    	int cnt=0;
    	for(int i=h[u];i!=-1;i=ne[i])
    	{
    		int v=e[i];
    		if(v!=pre)
    		{
    			int res=dfs(v,u);//边(u,v)v那边点的数量
    			cnt+=res;
    			ve.push_back(1ll*res*(n-res));//n-res是u这边的数量,乘积就是边(u,v)的贡献
    		}
    	}
        return cnt+1;//加上自身这个点
    }
    int main()
    {
        IOS
    	cin>>n;
    	memset(h,-1,sizeof h);
    	for(int i=1;i<n;i++)
    	{
    		int a,b;
    		cin>>a>>b;
    		add(a,b);
    		add(b,a);
    	}
    	dfs(1,-1);
    	sort(ve.begin(),ve.end());
    	long long ans=0;
    	for(int i=0;i<ve.size();i++)
    		ans+=1ll*ve[i]*(n-i-1);//按贡献一次递减赋值
    	cout<<ans;
    	return 0;
     } 
    

    H 每个物品都是以2进制的形式给出的,如果n个物品的和大于等于2 ^30那么一定可以装满。
    假设上面是对的,就会有三种情况,29的次数为0,1,2。如果有两个29,那么一定是可以的;如果只有一个29,那么剩余n-1个物品之和一定大于等于2^29,就和上面是类似的了;如果没有29,因为给出的都是二进制,所以可以把n个物品分为两部分,每部分的和都大于等于2 ^29,用这两部分取填满两个2 ^29的背包,又和上面类似了,这是看了题解后我的理解,貌似没问题吧
    所以把大的填进去一定可以填满吧

    #include<bits/stdc++.h>
    
    using namespace std;
    const int N = 1e5+5;
    typedef long long ll;
    int t;
    ll n,m,l,r,mid;
    int a[N];
    int main()
    {
        cin>>t;
        while(t--)
        {
            cin>>n;
            ll sum=0;
            for(int i=0;i<n;i++) cin>>a[i],sum+=(1ll<<a[i]);
            if(sum<(1ll<<30)) cout<<"impossible"<<endl;
            else 
            {
            	bool st[N]={0};
            	pair<int,int> b[N];
            	for(int i=0;i<n;i++) b[i]={a[i],i};
            	sort(b,b+n);
            	sum=0;
            	for(int i=n-1;i>=0;i--) 
            	{
            		sum+=(1ll<<b[i].first);
            		st[b[i].second]=1;
            		if(sum==(1ll<<30))
            		{
            			break;
    				}
    			}
    			for(int i=0;i<n;i++) cout<<st[i];
    			puts("");
    		}
        }    return 0;
    }
    

    I 可以找以最大的字符开头的后缀,比较一遍就可以了(数据范围小暴力找每一个子串也是可以的)

    #include<iostream>
    #include<string>
    using namespace std;
    string s;
    char c=0;
    int main()
    {
    	cin>>s;
    	for(int i=0;i<s.size();i++)
    		c=max(c,s[i]);
    	string st;
    	for(int i=0;i<s.size();i++)
    		if(s[i]==c)
    			st=max(st,s.substr(i));
    	cout<<st;
     } 
    

    J

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=100010,inf=0x3f3f3f3f;
    #define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tir(0);
    int n,a[N],l=-inf,r=inf;
    int main()
    {
        cin>>n;
        for(int i=0;i<n;i++){
            cin>>a[i];
            l=max(l,a[i]);
            r=min(r,a[i]);
        }
        cout<<l-r;
        return 0;
    }
    
  • 相关阅读:
    强连通分量
    mysql安装图解 mysql图文安装教程(详细说明)
    MeshCombineUtility.cs method `GetTriangleStrip' of type `UnityEngine.Mesh' could be found
    socket网络编程之一:客户端和服务器端接口函数
    unity3D——登录界面
    Ionic学习注意事项01
    这里我将分享我学到的几种ionic登陆界面
    关于ionic基础教程的学习网址
    Windows下配置Git
    Cocos网络篇[3.2](3) ——Socket连接(1)
  • 原文地址:https://www.cnblogs.com/neflibata/p/12871775.html
Copyright © 2020-2023  润新知