Sum of Log(2020上海C)

Posted Jozky86

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Sum of Log(2020上海C)相关的知识,希望对你有一定的参考价值。

Sum of Log

题意:

∑ i = 0 X ∑ j = [ i = 0 ] Y [ i & j = 0 ] ⌊ l o g 2 ( i + j ) + 1 ⌋ \\sum_{i=0}^{X}\\sum_{j=[i=0]}^{Y}[i\\&j=0]\\lfloor log_{2}(i+j)+1\\rfloor i=0Xj=[i=0]Y[i&j=0]log2(i+j)+1

题解:

数位dp
如果式子想有意义,i&j就要等于0,也就是i和j的任何一位都不能同时为1,那么i+j就不会产生进位,也就是 ⌊ l o g 2 ( i + j ) + 1 ⌋ \\lfloor log_{2}(i+j)+1\\rfloor log2(i+j)+1的值就是位数最长的那个数,也就是说i和j中最高位的1是第几位就是 ⌊ l o g 2 ( i + j ) + 1 ⌋ \\lfloor log_{2}(i+j)+1\\rfloor log2(i+j)+1的值
所以我们对于每一个最高位(也就是枚举 ⌊ l o g 2 ( i + j ) + 1 ⌋ \\lfloor log_{2}(i+j)+1\\rfloor log2(i+j)+1的值),取求i&j==0的个数有多少个,相乘就是答案
代码中的num表示当前位是否是最高位(0表示当前是最高位,1表示不是)

代码:

#include <bits/stdc++.h>
#include <unordered_map>
#define debug(a, b) printf("%s = %d\\n", a, b);
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
clock_t startTime, endTime;
//Fe~Jozky
const ll INF_ll= 1e18;
const int INF_int= 0x3f3f3f3f;
void read(){};
template <typename _Tp, typename... _Tps> void read(_Tp& x, _Tps&... Ar)
{
    x= 0;
    char c= getchar();
    bool flag= 0;
    while (c < '0' || c > '9')
        flag|= (c == '-'), c= getchar();
    while (c >= '0' && c <= '9')
        x= (x << 3) + (x << 1) + (c ^ 48), c= getchar();
    if (flag)
        x= -x;
    read(Ar...);
}
template <typename T> inline void write(T x)
{
    if (x < 0) {
        x= ~(x - 1);
        putchar('-');
    }
    if (x > 9)
        write(x / 10);
    putchar(x % 10 + '0');
}
void rd_test()
{
#ifdef ONLINE_JUDGE
#else
    startTime = clock ();
    freopen("data.in", "r", stdin);
#endif
}
void Time_test()
{
#ifdef ONLINE_JUDGE
#else
    endTime= clock();
    printf("\\nRun Time:%lfs\\n", (double)(endTime - startTime) / CLOCKS_PER_SEC);
#endif
}
const int mod=1e9+7;
const int maxn=50; 
int lg[maxn];
int a[40],b[40];
ll dp[40][2][2];
ll res=0;
ll dfs(int len,int flag1,int flag2,bool num){
	if(!len)return 1;
	if(dp[len][flag1][flag2]!=-1)return dp[len][flag1][flag2]%mod;
	int up1=flag1?a[len]:1;
	int up2=flag2?b[len]:1;
	ll ans=0,cnt=0;
	for(int i=0;i<=up1;i++){
		for(int j=0;j<=up2;j++){
			if((i&&j))continue;
			int tmp=dfs(len-1,flag1&&(i==up1),flag2&&(j==up2),num||i||j)%mod;
			ans=(ans+tmp)%mod; 
			if(num==0&&(i|j))
				cnt=(cnt+tmp)%mod;
		}
	}
	res=(res+cnt*len)%mod;
	return dp[len][flag1][flag2]=ans%mod;
}
ll solve(ll x,ll y){
	res=0;
	memset(dp,-1,sizeof(dp));
	memset(a,0,sizeof(a));
	memset(b,0,sizeof(b));
	int cnt1=0;
	while(x){
		a[++cnt1]=x%2;
		x>>=1;
	}
	int cnt2=0;
	while(y){
		b[++cnt2]=y%2;
		y>>=1;
	}
	
	ll ans=dfs(max(cnt1,cnt2),1,1,0);
	return res%mod;
}
int main()
{
    rd_test();
	lg[0]=-1;
	for(int i=1;i<=40;i++)lg[i]=lg[i>>1]+1;
    int t;
    read(t);
    while(t--){
    	ll x,y;
    	read(x,y);
    	cout<<solve(x,y)<<endl;
	}
	return 0;
	//Time_test();
}




以上是关于Sum of Log(2020上海C)的主要内容,如果未能解决你的问题,请参考以下文章

45届ICPC亚洲区域赛(上海)C.Sum of Log(卡常数位dp)

leetcode_1292. Maximum Side Length of a Square with Sum Less than or Equal to Threshold_[二维前缀和](代码片段

1 代码片段1

1104 Sum of Number Segments(二刷)

CF 489 C Given Length and Sum of Digits... 贪心

ICPC20上海C——小白也能秒懂的数位dp讲解