2 条题解

  • 0
    @ 2026-6-9 12:50:24

    当我不想做数学题时:

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    const int N=2e5+10,P=1e9+7;
    int dp[N],n;
    string s;
    int dfs(int x,int lim)
    {
    	if(x==0)return dp[x]=1;
    	if(!lim&&dp[x])return dp[x];
    	int up=lim?s[n-x]-'0':1,ans=0;
    	for(int i=0;i<=up;i++)
    	{
    		if(i==0)ans=(ans+dfs(x-1,lim&&i==up))%P;
    		else ans=(ans+dfs(x-1,lim&&i==up)*2)%P;
    	}
    	if(!lim)dp[x]=ans;
    	return ans;
    }
    signed main()
    {
    	cin>>s;n=s.size();
    	cout<<dfs(n,1)<<'\n';
    	return 0;
    }
    • 0
      @ 2026-6-9 11:46:31

      题意

      以二进制形式给出一个整数 LL ,问有多少个非负整数对 (a,b)(a, b) 满足:a+b=abLa+b = a \oplus b \le L。答案对 109+710^9+7 取模。

      题解

      首先,因为异或相比加法只能让两个一变成零,而不能产生新的一,所以不可以产生进位。

      f[i][1]f[i][1] 表示 a+ba+b 二进制前 ii 个刚好是 LL 的前 ii 位的方案数,f[i][0]f[i][0] 是严格小于 LL 的方案数。

      LL 当前位为 11, 那么恰好等于 LL 时, a,ba,b 可以分别填 0,10, 11,01, 0, 所以 f[i][1]=f[i1][1]×2f[i][1] = f[i-1][1] \times 2。当前位为 00f[i][1]=f[i1][1]f[i][1] = f[i-1][1]

      考虑不严格小于的情况,若前面已经严格小于了,那么这一位可以随便填,不进位就行,有 a,ba,b 当前位为 0,11,00,00,1|1,0 | 0,0 的三种情况,f[i][0]=f[i1][0]×3f[i][0] = f[i-1][0] \times 3, 还有一种情况是前面都相等,刚刚从这一位开始不相等,仅在 LL 当前位是 11 时有这种情况,只能填 0,00,0, 所以此时 f[i][0]=f[i1][0]×3+f[i1][1]f[i][0] = f[i-1][0] \times 3 + f[i-1][1]

      代码

      代码很短,只有 99

      #include <cstdio>
      long long f0 = 0, f1 = 1, p = 1000000007, s;
      signed main() {
      	while(scanf("%c", &s) != EOF && (s == '0' || s == '1')) {
      		f0 = f0 * 3 % p;
      		if(s == '1') f0 = (f0 + f1) % p, f1 = f1 * 2 % p;
      	}
      	printf("%lld", (f0+f1) % p);
      }
      

      我不会告诉你把 s 定义成 long long 仅仅是为了美观的。

      • 1

      信息

      ID
      11669
      时间
      2000ms
      内存
      1024MiB
      难度
      9
      标签
      递交数
      88
      已通过
      5
      上传者