[hdu5632][BC#73 1002]Rikka with Array

  点开BC发现今晚没比赛。。然后似乎上一场有数位DP?...(幸好我没去

  一开始被BCDcode那题的思路带歪了。。后来发现得把n转成二进制才能搞TAT

 

  题目大概是要求一种类似逆序对的鬼东西:

    有一个长度为 n 的数组 A(下标为 1 到 n),A_i​​ 为 i 的二进制表示中的1的个数,例如 A[1]=1, A[3]=2, A[10]=2。

    现在勇太想知道数组 A 中满足 A[ i ]>A[ j ] 的数对 ( i , j )(1 ≤ i < j ≤ n) 的个数。


  f[i][j]表示二进制下,i位的数有j个1的方案数(其实也就是组合数了

  再预处理出g[i]表示二进制下,i位的数中,满足题意的数对的个数。

  统计的时候用pre[i]表示 之前的数中,1的个数为i的数的个数。

  其实有点像逆序对的那题(hdu5225)

  统计的时候,一开始脑残写了发树状数组,然后复杂度比正解多一个log神奇的200+ms过了(中途还在纠结树状数组怎么写233)

  吐槽了一下数据强度,然后发现自己傻逼了...弄个变量记录就行了TAT。。所以总的时间复杂度是O(10 * log²n)(logn是<1000的)

  然后就46ms跑过去啦。。并列#1。。。(因为是新题...目前这题才30+人过... 实在没法再卡常了

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #define ll long long
 5 #define MOD(x) x-=x>=modd?modd:0
 6 #define modd 998244353
 7 using namespace std;
 8 
 9 int f[1000][1000],g[1003],nowsm[1003],pre[1003];
10 int two[12];
11 int i,j,k,n,m,len,len1;
12 char s1[333],s[1003];
13 
14 inline void turn(){
15     len=0;
16     register int i,l=1;
17     while(l<=len1&&s1[l]){
18         s[++len]=s1[len1]&1;
19         for(i=l;i<=len1;i++)
20             s1[i+1]+=(s1[i]&1)?10:0,s1[i]>>=1;
21         if(!s1[l])l++;
22     }
23 }
24 
25 inline int get(){
26     register int i,pr=0,sm;int ans=g[len-1];
27     memset(pre,0,sizeof(pre));
28     memcpy(pre,f[len-1],len<<2);
29     pr=1;
30     for(i=len-1;i;pr+=s[i--])
31         if(s[i]){
32             for(ans+=g[i-1],MOD(ans),sm=0,j=len;j>=pr;j--)
33                 sm+=pre[j],MOD(sm);
34             for(j=0,k=pr;j<=i;j++,k++)
35                 sm-=pre[k],sm+=sm<0?modd:0,
36                 ans=(ans+(ll)f[i-1][j]*sm)%modd,
37                 pre[k]+=f[i-1][j],MOD(pre[k]);
38         }
39     for(i=len;i>pr;i--)ans+=pre[i],MOD(ans);
40     return ans;
41 }
42 int main(){
43     register int i,j;
44     for(i=0;i<=999;i++)f[i][0]=1;f[1][1]=1;
45     for(i=2,g[1]=0;i<=999;i++){
46         g[i]=g[i-1]<<1,MOD(g[i]);
47         ll sm=0;
48         for(j=1;j<=i;j++)
49             sm+=f[i-1][j],f[i][j]=f[i-1][j]+f[i-1][j-1],MOD(f[i][j]);
50         for(j=0;j<i;j++)
51             sm-=f[i-1][j+1],
52             g[i]=(g[i]+sm%modd*f[i-1][j])%modd;
53     }
54     
55     int T;scanf("%d",&T);
56     while(T--){
57         scanf("%s",s1);len1=strlen(s1);for(i=len1;i;i--)s1[i]=s1[i-1]-48;
58         turn(),
59         printf("%d
",get());
60     }
61     return 0;
62 }
View Code
原文地址:https://www.cnblogs.com/czllgzmzl/p/5223470.html