首页 > 其他分享 >[每日一题] - CF1982E

[每日一题] - CF1982E

时间:2024-07-05 22:42:55浏览次数:17  
标签:int 每日 sum1 CF1982E sum now ll define

校内作业多,一直忘记写blog

现在开始补上量

赛后几天秒掉了,场上真是困糊涂了,没想到分治

#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
#define ll long long
#define node pair<int,pair<ll,ll>>
#define mp(x,y,z) make_pair(x,make_pair(y,z))
#define fi first
#define se second.first
#define th second.second
int t,k;
ll n;
map<pair<ll,int>,node> p;
node solve(ll n,int k){
	if(p.count(make_pair(n,k)))return p[make_pair(n,k)];
	if(k<0)return p[make_pair(n,k)]=mp(0,0LL,0LL);
	if(n==1)return p[make_pair(n,k)]=mp(1,1LL,1LL);
//	printf("%lld %d\n",n,k);
	for(int m=62;m>=0;m--){
		if((1LL<<m)<n){
			node res1=solve(1LL<<m,k),res2=solve(n-(1LL<<m),k-1);
			node res=mp((res1.fi+res2.fi)%mod,0,0);
			if(res1.se==(1LL<<m))res.se=res1.se+res2.se;
			else res.se=res1.se;
			if(res2.th==n-(1LL<<m))res.th=res1.th+res2.th;
			else res.th=res2.th;
			res.fi=(res.fi+1LL*res1.th%mod*(res2.se%mod))%mod;
			return p[make_pair(n,k)]=res;
		}
	}
}
int main(){
	scanf("%d",&t);
	while(t--){
		scanf("%lld%d",&n,&k);
		printf("%d\n",solve(n,k).fi);
	}
	return 0;
}

附考场唐氏代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pli pair<ll,int>
#define mp make_pair
#define fi first
#define se second
#define It set<pair<ll,int>>::iterator
const int mod=1e9+7;
int ksm(int x,int y){
	int res=1;
	while(y){
		if(y&1)res=1LL*res*x%mod;
		x=1LL*x*x%mod;
		y>>=1;
	}
	return res;
}
int T,k;
ll n,res;
set<pli> s[65];
int calc_min(ll l,ll r){
	int sum=0,sum1=0;
	for(int i=60;i>=0;i--)sum1+=(l>>i)&1;
	for(int i=60;i>=0;i--){
		int a=(l>>i)&1,b=(r>>i)&1;
		if(a!=b){
			if(i==0)return min(sum,sum1);
			else return min(sum+1,sum1);
		}
		if(a==1)sum++;
	}
	return min(sum,sum1);
}
int calc_max(ll l,ll r){
	int sum=0,sum1=0;
	for(int i=60;i>=0;i--)sum1+=(r>>i)&1;
	for(int i=60;i>=0;i--){
		int a=(l>>i)&1,b=(r>>i)&1;
		if(a!=b){
			if(i==0)return max(sum+1,sum1);
			else return max(sum+i,sum1);
		}
		if(a==1)sum++;
	}
	return max(sum,sum1);
}
int main(){
	scanf("%d",&T);
	while(T--){
		scanf("%lld%d",&n,&k);
		ll now=0;res=0;
		s[k].insert(mp(n,0));
		It it=s[k].find(mp(n,0));
		if(it!=s[k].begin())now=(*prev(it)).fi+1,res=(*prev(it)).se;
		s[k].erase(mp(n,0));
		if(calc_max(now,now)>k){
			ll l=now+1,r=n-1,fin=now;
			while(l<=r){
				ll mid=(l+r>>1);
				if(calc_min(now,mid)>k)fin=mid,l=mid+1;
				else r=mid-1;
			}
			now=fin+1;
		}
		while(now<n){
			ll l=now+1,r=n-1,fin=now;
			while(l<=r){
				ll mid=(l+r>>1);
				if(calc_max(now,mid)<=k)fin=mid,l=mid+1;
				else r=mid-1;
			}
			ll len=fin-now+1;now=fin+1;
			len%=mod;res+=len*(len+mod-1)%mod*ksm(2,mod-2);res%=mod;
			res+=len;res%=mod;
			if(fin!=n-1)s[k].insert(mp(now,res));
			l=now+1,r=n-1,fin=now;
			while(l<=r){
				ll mid=(l+r>>1);
				if(calc_min(now,mid)>k)fin=mid,l=mid+1;
				else r=mid-1;
			}
			now=fin+1;
		}
		printf("%lld\n",res);
	}
	return 0;
} 

标签:int,每日,sum1,CF1982E,sum,now,ll,define
From: https://www.cnblogs.com/kentsbk/p/18286712

相关文章

  • 代码随想录算法训练营第五十三天 | 739.每日温度 496.下一个更大的元素I 503.下一个更
    739.每日温度题目链接文章讲解视频讲解单调栈适合的场景:求当前元素左面或右面第一个比它大或小的元素单调栈里存什么元素只要存下标就可以了,比较元素时可以通过下标取元素单调栈是单调增还是单调减(从栈顶到栈底)使用单调增的单调栈解题步骤:遍历数组,当栈空时直接入栈......
  • 【力扣】每日一题—第88题,合并两个有序数组
    目录题目暴力求解思路:通过代码:拓展学习:最终代码如下:题目给你两个按**非递减顺序**排列的整数数组`nums1`和`nums2`,另有两个整数`m`和`n`,分别表示`nums1`和`nums2`中的元素数目。请你**合并**`nums2`到`nums1`中,使合并后的数组同样按**非递减顺序*......
  • 【力扣】每日一题—第35题,搜索插入位置
    题目:给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。注意点:没有这个数要返回大于这个数的下标思想:for循环找到target的值,返回下标,加判断如果没有这个值,找出小于这个值和第二个数大于的区间,将第二个......
  • 每日一道算法题 判断子序列
    题目判断子序列_牛客题霸_牛客网(nowcoder.com)Python##代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可###@paramSstring字符串#@paramTstring字符串#@returnbool布尔型#classSolution:defisSubsequence(self,S:str......
  • 每日一道算法题 称砝码
    题目称砝码_牛客题霸_牛客网(nowcoder.com)Pythonn=int(input())weight=list(map(int,input().split()))count=list(map(int,input().split()))w_li=[]for_inrange(n):foriinrange(count[_]):w_li.append(weight[_])ans={0}forwinw_li:......
  • 【每日一练】python小学生选择题小程序
    """小学生作业题小程序要求:答对一题得10有得分奖励"""分数=0print("""一、选择题(总题10道,总分100)1.在公路上踢球属于()安全隐患A.校园B.交通C.用电 """)t1=input("请选择:").lower()ift1=="b":分数+=10print(&......
  • 【每日一练】python写一个计算烟龄小程序
     PS:因不懂英语,命名用中文,各位见笑了代码:print("算一算这辈子你吸了多少烟?")   姓名=input("请输入您的名字:")烟龄=int(input("您的烟龄(年):"))   每天=int(input("您一天多少包:"))总烟数=20*每天*365*烟龄/10000print(f"{姓名},您一共大约吸了{总烟数}万根......
  • JAVA每日作业day7.1-7.3小总结
    ok了家人们前几天学了一些知识,接下来一起看看吧一.APIJava的API(API:Application(应用)Programming(程序) Interface(接口))JavaAPI就是JDK中提供给我们使用的类,这些类将底层的代码实现封装了起来,我们不需要关心这些类是如何......
  • 每日一题:Leetcode-102 二叉树的层序遍历
    力扣题目解题思路java代码力扣题目:给你二叉树的根节点 root ,返回其节点值的 层序遍历 。(即逐层地,从左到右访问所有节点)。示例1:输入:root=[3,9,20,null,null,15,7]输出:[[3],[9,20],[15,7]]示例2:输入:root=[1]输出:[[1]]示例3:输入:root=[]输出:[]......
  • 【每日一练】python列表
    1、输入一个整数列表,将列表中的元素按照逆序输出。list1=[5,4,5,6]list1.reverse()print(list1)[6,5,4,5]2、输入一个字符串列表,输出其中长度大于等于5的字符串,并且将它们转换为大写形式。list1=['hello','lol','ak47','aliang']foriinlist1:iflen(i)......