Description
As we know, Rikka is poor at math. Yuta is worrying about this situation, so he gives Rikka some math tasks to practice. There is one of them:
Yuta has an array A of length n,and the ith element of A is equal to the sum of all digits of i in binary representation. For example,A[1]=1,A[3]=2,A[10]=2.
Now, Yuta wants to know the number of the pairs (i,j)(1≤i<j≤n) which satisfy A[i]>A[j].
It is too difficult for Rikka. Can you help her?
Input
The first line contains a number T(T≤10)——The number of the testcases. For each testcase, the first line contains a number n(n≤10300).
Output
For each testcase, print a single number. The answer may be very large, so you only need to print the answer modulo 998244353.
Sample Input
1 10
Sample Output
7
题意:给定一个数$n(nleq 10^{300})$,问有多少个数对$(i , j)$,满足$1leq i<j leq n$且$f[i]>f[j]$,$f[x]$为$x$二进制表示下$1$的个数。
分析:(在打模拟赛时写到的题目……好像写了一种跟所有人都不一样的写法)
首先考虑一个数$x$,我们需要统计满足$1leq i<x$且$f[i]>f[x]$的$i$的个数。考虑数位dp,将$x$转为二进制形式,从低位往高位推。假设当前在第$i$位,从第$1$位到第$i$位共有$k$个$1$:若当前位为$0$,则直接跳过进行下一位的统计;否则钦定当前要统计进答案的数字的比第$i$位高的位置与$x$相同,且第$i$位为$0$,则此时最低的第$i-1$位至少要有$k+1$个$1$,可任意选取,即需要统计进答案里的方案数为$sum _{j=k+1}^{i-1} inom{i-1}{j}$ ,令$s(i,j)=sum _{d=0}^{j}inom{i}{d}$,则公式简化为$s(i-1,i-1)-s(i-1,k)$。
现在我们需要统计总答案,且因为$n$很大,无法直接枚举。考虑将$n$转成二进制形式,共有$cnt$位,$a_{i}$为$n$在二进制下第$i$位上的数字。统计每一个$s(i-1,i-1)-s(i-1,k)$被统计进答案的贡献。若$s(i-1,i-1)-s(i-1,k)$会在数字$x$时被统计进答案里,$x$需要满足以下几个条件:1.$1leq xleq n$,2. $x$的第$i$位为$1$,3.$x$的前$i$位恰好有$k$个$1$。答案转化为统计满足条件的$x$的个数。
我们递推一个数组$f$,$f(i,j)$表示数值小于等于$n$最低的$i$位,且二进制下恰好含有$j$个$1$的数字的方案数。可得:
$$f(i,j)=egin{cases}f(i-1,j)~~~~~~~~~~~~~~~~~~~~~~~(a_{i}=0)\f(i-1,j-1)+inom{i-1}{j}~~~(a_{i}=1)end{cases}$$
特殊的,$f(i,0)=1(0leq ileq cnt)$。然后就可以数位dp出对于每一个$(i-1,k)$的组合,所有符合条件的数$x$了。
枚举当前在第$i$位,前$i-1$位总共有$k$个$1$,我们令$num=sum _{d=i+1}^{cnt} 2^{d-(i+1)}cdot a_{d}$,即大于第$i$位的部分的$0$到$num-1$的方案,则$s(i-1,i-1)-s(i-1,k+1)$的系数$t$计算方式如下:
$$t=egin{cases}numcdot inom{i-1}{k}~~~~~~~~~~~~~~~~~~~~~~~~~(a_{i}=0)\numcdot inom{i-1}{k}+f(i-1,k)~~~(a_{i}=1)end{cases}$$
然后就可以得到最终的答案了。

1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #define LL long long 5 using namespace std; 6 const int N=1e3+5; 7 const int mod=998244353; 8 int T,n,cnt,ans,tmp,num,now,t; 9 int x[N],a[N],C[N][N],s[N][N],f[N][N]; 10 char ch[N]; 11 int read() 12 { 13 int x=0,f=1;char c=getchar(); 14 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 15 while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} 16 return x*f; 17 } 18 void Mod(int& a,int b){a+=b;if(a>=mod)a-=mod;} 19 int main() 20 { 21 for(int i=0;i<=1000;i++)C[i][0]=1; 22 for(int i=1;i<=1000;i++) 23 for(int j=1;j<=i;j++) 24 C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod; 25 for(int i=0;i<=1000;i++) 26 for(int j=0;j<=1000;j++) 27 if(j)s[i][j]=(s[i][j-1]+C[i][j])%mod; 28 else s[i][j]=C[i][j]; 29 T=read(); 30 while(T--) 31 { 32 cnt=ans=0; 33 scanf("%s",ch+1); 34 n=strlen(ch+1); 35 for(int i=1;i<=n;i++)x[n-i+1]=ch[i]-'0'; 36 if(n==1&&(x[1]==0||x[1]==1)){printf("0 ");continue;} 37 while(n) 38 { 39 if(x[1]&1)a[++cnt]=1,x[1]--; 40 else a[++cnt]=0; 41 for(int i=n;i>=1;i--) 42 if(x[i]&1)x[i]/=2,x[i-1]+=10; 43 else x[i]/=2; 44 while(n&&x[n]==0)n--; 45 } 46 memset(f,0,sizeof(f)); 47 for(int i=0;i<=cnt;i++)f[i][0]=1; 48 for(int j=1;j<=cnt;j++) 49 for(int i=j;i<=cnt;i++) 50 if(!a[i])Mod(f[i][j],f[i-1][j]); 51 else 52 { 53 Mod(f[i][j],f[i-1][j-1]); 54 Mod(f[i][j],C[i-1][j]); 55 } 56 for(int i=1;i<=cnt;i++) 57 { 58 num=0; 59 for(int j=cnt;j>i;j--)num=(num*2+a[j])%mod; 60 for(int j=0;j<i;j++) 61 { 62 t=1ll*num*C[i-1][j]%mod; 63 Mod(ans,1ll*(s[i-1][i-1]-s[i-1][j+1]+mod)%mod*t%mod); 64 if(!a[i])continue; 65 Mod(ans,1ll*(s[i-1][i-1]-s[i-1][j+1]+mod)%mod*f[i-1][j]%mod); 66 } 67 } 68 printf("%d ",ans); 69 } 70 return 0; 71 }