zoukankan      html  css  js  c++  java
  • CCPC

    A 完全k叉树

    题意

    已知完全(k)叉树有(n)个节点,求树上两个最远点的距离,节点之间的距离均为1。

    基本思路

    求树的深度(h),则满(k)叉树的两点距离为((h-1)*2),对剩余一层的节点数(rest)做判断,若(rest>k^{h-1}/k)则ans+2,否则若(rest>0,ans+1)

    #include<bits/stdc++.h> 
    #define FOR(i,a,b) for(int i=a;i<b;i++)
    #define FOR2(i,a,b) for(int i=a;i<=b;i++)
    #define sync ios::sync_with_stdio(false);cin.tie(0) 
    #define ll long long
    #define MAXN 100010
    using namespace std;
    int main()
    {
    	ll count=0,t,n,k;cin>>t;
    	while(t--)
    	{
    		count=0;ll h=0;
    		cin>>k>>n;
    		if(k==1){
    			cout<<n-1<<endl;continue;
    		}
    		ll sum=0,tmp=1;
    		while(1)
    		{
    			sum+=tmp;
    			tmp*=k;
    			h++;
    			if(tmp+sum>=n)break; 
    		}
    		ll ans=(h-1)*2;
    		n=n-sum;
    		if(n>tmp/k)
    		{
    			ans+=2;
    		}
    		else if(n>=1)
    		{
    			ans++;
    		}
    		
    		cout<<ans<<endl;
    		
    	}
    	return  0;
    }
    

    B 距离产生美

    题意

    一串数,求使的所有相邻数的差(>=k)的最小修改数

    基本思路

    差分,然后扫描,若扫到某个间隔(<k)则记(cnt++,i++)
    注意绝对值

    #include<bits/stdc++.h> 
    #define FOR(i,a,b) for(int i=a;i<b;i++)
    #define FOR2(i,a,b) for(int i=a;i<=b;i++)
    #define sync ios::sync_with_stdio(false);cin.tie(0) 
    #define ll long long
    #define MAXN 100010
    using namespace std;
    int arr[MAXN],brr[MAXN];
    int main()
    {	
    	ll n,k,cnt=0;cin>>n>>k;
    	 FOR(i,0,n){
    	 	cin>>arr[i];
    	 	if(i!=0)brr[i]=arr[i]-arr[i-1];
    	 }
    	 FOR(i,1,n)
    	 {
    	 	if(abs(brr[i])<k)
    		 {
    		 	cnt++;
    		 	i++;
    		 }
    	 }
    	 cout<<cnt<<endl;
    	return 0;
    }
    

    C 烤面包片

    基本题意

    (n!!!)(k)模的结果

    基本思路

    若某次求累乘的时候,(n>=mod)则结果必为0,因此循环必定不会超过(k)

    #define FOR(i,a,b) for(int i=a;i<b;i++)
    #define FOR2(i,a,b) for(int i=a;i<=b;i++)
    #define sync ios::sync_with_stdio(false);cin.tie(0) 
    #define ll long long
    #define MAXN 100010
    using namespace std;
    int main()
    {
    	ll n,mod,ans=1;
    	cin>>n>>mod;
    	if(n>=mod)
    	{
    		cout<<0<<endl;return 0;
    	}
    	FOR(i,1,n+1)
    	{
    		ans=(ans*i);
    		if(ans>=mod)
    		{
    			cout<<0<<endl;return 0;
    		}
    	}
    	n=ans;ans=1;
    	FOR(i,1,n+1)
    	{
    		ans=(ans*i);
    		if(ans>=mod)
    		{
    			cout<<0<<endl;return 0;
    		}
    	}
    	n=ans;ans=1;
    	FOR(i,1,n+1)
    	{
    		ans=(ans*i)%mod;
    	}
    	cout<<ans<<endl;
    	return 0;
    }
    

    F 三元组

    题意

    (n)个三元组((a_i,b_i,c_i))若一对([i,j](i<=j)),满足(2*min(a_i+a_j,b_i+b_j)le{max(a_i+a_j,b_i+b_j)})则得到c_i*c_j的钱,输出求和模1e9+7的值

    基本思路

    每个三元组增加一个属性(2*a_i-b_i),对此属性排序,求(c_i)的前缀和sum,然后手动二分求(max(posr),使得(2*a_1+2*a_{posr}-b_1-b_{posr}<=0))
    ([1,posr])选择起点,然后从后往前扫描确定终点,因为若([i,j]),则必有([i+1,k](k<=j));找到后,用(c_i*sum[i,j])求出此次增加的钱。要两次排序。

    #include<bits/stdc++.h> 
    #define FOR(i,a,b) for(int i=a;i<b;i++)
    #define FOR2(i,a,b) for(int i=a;i<=b;i++)
    #define sync ios::sync_with_stdio(false);cin.tie(0) 
    #define ll long long
    #define MAXN 100010
    #define MOD (1000000000+7)
    #define debug cout<<"debug"<<endl
    using namespace std;
    typedef struct{
    	ll a,b,c,trans;
    }NODE;NODE nodes[MAXN];
    ll n,sum[MAXN];
    bool cmp(NODE n1,NODE n2)
    {
    	return n1.trans<n2.trans;
    }
    ll solve()
    {
    	sort(nodes+1,nodes+n+1,cmp);
    	sum[1]=nodes[1].c;
    	FOR2(i,2,n)
    	{
    		sum[i]=nodes[i].c+sum[i-1];
    	}
    	ll l=1,r=n,posr=0;
    	while(l<=r)
    	{ 	
    		ll mid=(l+r)/2;
    		if(nodes[mid].trans+nodes[1].trans>0){
    			r=mid-1;
    		} 
    		else {
    			posr=mid;l=mid+1;
    		}
    	}
    	ll res=0;
    	for(l=1,r=posr;l<=r;l++)
    	{//确定起点		
    		while(l<=r&&nodes[l].trans+nodes[r].trans>0) {
    			r--;
    			posr--;
    		}
    		if(r<l) break;
    		res=(res+((sum[r]-sum[l-1])%MOD)*nodes[l].c)%MOD; //L~R的和 
    	}
    	return res; 
    }
    int main()
    {
    	cin>>n;
    	FOR2(i,1,n)
    	{
    		cin>>nodes[i].a>>nodes[i].b>>nodes[i].c;
    		nodes[i].trans=2*nodes[i].a-nodes[i].b;
    	}
    	ll ans=solve();
    	FOR2(i,1,n)
    	{
    		nodes[i].trans=2*nodes[i].b-nodes[i].a;
    	}
    	ans+=solve();
    	cout<<ans%MOD<<endl;
    	
    	return 0;
    }
    

    G 篮球校赛

    题意

    n个人,每人5个属性,求选出5人的最大属性和,每个属性只能选择一人。

    基本思路

    使用插排,选出每个属性排名前五的人,然后dfs暴搜

    #include<bits/stdc++.h> 
    #define FOR(i,a,b) for(int i=a;i<b;i++)
    #define FOR2(i,a,b) for(int i=a;i<=b;i++)
    #define sync ios::sync_with_stdio(false);cin.tie(0) 
    #define ll long long
    #define MAXN 100010
    using namespace std;
    typedef struct{
    	int state[6];
    }NODE;NODE nodes[MAXN];
    int maxp[6][6];
    int vis[MAXN];
    ll ans=0;int n;
    void dfs(ll level,ll res)
    {
    	if(level==6)
    	{
    		ans=max(ans,res); 
    		return;
    	}
    	else {
    		for(int i=1;i<=5;i++)
    		{
    			if(vis[maxp[i][level]]==1)continue;
    			vis[maxp[i][level]]=1;//记录选择的队员 
    			dfs(level+1,res+nodes[maxp[i][level]].state[level]);
    			vis[maxp[i][level]]=0;
    		}
    	}
    }
    int main()
    {
    	cin>>n;
    	FOR2(i,1,n)
    	{
    		for(int j=1;j<=5;j++)
    		{
    			cin>>nodes[i].state[j];
    			for(int k=1;k<=5;k++)
    			{//逐个与5个元素比较 
    				if(nodes[i].state[j]>nodes[maxp[k][j]].state[j])
    				{//插入排序 
    					for(int h=5;h>=k+1;h--)
    						maxp[h][j]=maxp[h-1][j];
    					maxp[k][j]=i;
    					break;
    				}	
    				
    			}
    		}
    	}
    	for(int i=1;i<=5;i++)
    	{
    		vis[maxp[i][1]]=1;
    		dfs(2,nodes[maxp[i][1]].state[1]);
    		vis[maxp[i][1]]=0;
    	}
    	cout<<ans<<endl; 
    	return 0;
    }
    

    H 分配学号

    题意

    给一串数,求使得他们互不相同的需要增加的最小数和,每个数只能增加不能减。

    基本思路

    排序,然后求出每个人可选择的数量,即能上升的最小数量(若小于前一个,则最少要上升到比前一个+1),(max(a[i-1]+1,a[i])-a[i]+1),注意不变也是一种选择,然后累乘。

    #include<bits/stdc++.h> 
    #define FOR(i,a,b) for(int i=a;i<b;i++)
    #define FOR2(i,a,b) for(int i=a;i<=b;i++)
    #define sync ios::sync_with_stdio(false);cin.tie(0) 
    #define ll long long
    #define MAXN 100010
    #define MOD (1000000000+7)
    using namespace std;
    ll n,arr[MAXN],brr[MAXN];
    int main()
    {
    	cin>>n;
    	FOR2(i,1,n)
    	{
    		cin>>arr[i];
    	}
    	sort(arr+1,arr+1+n);
    	ll ans=1;
    	FOR2(i,1,n)
    	{
    		if(i!=1)
    		{
    			brr[i]=max(arr[i-1]+1,arr[i])+1-arr[i];
    			arr[i]=max(arr[i-1]+1,arr[i]);
    			ans=(ans*brr[i])%MOD;
    		}
    			
    	}
    	cout<<ans%MOD<<endl;
    	return 0;
    }
    

    I Gree的心房

    题意

    给n*m的矩阵和k个箱子,箱子随意摆放,求从左上到右下的最短路径长,若不能达到输出-1;

    基本思路

    k最大不超过(n-1)(m-1),路径为n+m-2

    #include<bits/stdc++.h> 
    #define FOR(i,a,b) for(int i=a;i<b;i++)
    #define FOR2(i,a,b) for(int i=a;i<=b;i++)
    #define sync ios::sync_with_stdio(false);cin.tie(0) 
    #define ll long long
    #define MAXN 100010
    using namespace std;
    int main()
    {
    	ll n,m,k;cin>>n>>m>>k;
    	if(k>(n-1)*(m-1)) {
    		cout<<-1<<endl; 
    	}
    	else{
    		cout<<n+m-2<<endl;
    	}
    	return 0;
    }
    
  • 相关阅读:
    Timed Code
    jQuery的deferred对象详解
    ASP.NET MVC 使用Redis共享Session
    .NET垃圾回收(GC)原理
    强命名程序集,签名,延迟签名
    CLR 关于强命名程序集 .
    .NET程序集强命名删除与再签名技术 源代码剖析
    应用Strong Name保存.NET应用程序集
    使用强命名程序集防范篡改
    1.浅谈CLR
  • 原文地址:https://www.cnblogs.com/tldr/p/11263186.html
Copyright © 2011-2022 走看看