Aggregated Counting(找规律 + 预处理)

Posted mrh-acmer

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Aggregated Counting(找规律 + 预处理)相关的知识,希望对你有一定的参考价值。

Aggregated Counting

转 : https://blog.csdn.net/cq_phqg/article/details/48417111

题解:

可以令n=1+2+2+3+3+......+ i    这个序列的长度为p

那么a[n]=1*1+2*2+3*2+...... + p*i 

那么不难发现a[a[n]] = 1*1 + (2+3)*2 + (4+5)*3 + (6+7+8)*4 + ... + (pre+1 + pre+2 + ... + pre+b[p] ) * p

b[p]为p在原序列中出现的次数

pre,b[p]这些值都可以预处理算出   每次询问可以O(1)算出答案

pre 是 第p-1项的pre + b[p-1]

 

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
 
typedef long long ll;
const int MOD = (int)1e9+7;
const int INF = (int)1e9;
const int MAXN = 438744;
int a[MAXN+5];
int b[MAXN+5];
int sum[MAXN+5];
int dp[MAXN+5];
int pre[MAXN+5];
int sz,val;
 
int add(int x,int y){
    x+=y;
    if(x>=MOD)x-=MOD;
    return x;
}
 
int po(int x,int n){
    int ans=1;
    int temp=x;
    while(n){
        if(n&1)ans=(ll)ans*temp%MOD;
        temp=(ll)temp*temp%MOD;
        n>>=1;
    }
    return ans;
}
 
int main()
{
    val=po(2,MOD-2);
    a[1]=1;
    a[2]=2;
    a[3]=2;
    int sz=3;
    for(int i=3;;i++){
        int cnt=a[i];
        while(cnt){
        a[++sz]=i;
        cnt--;
        if(sz>=MAXN)break;
        }
        if(sz>=MAXN)break;
    }
    for(int i=1;i<=MAXN;i++){
        sum[i]=sum[i-1]+a[i];
        if(sum[i]>=INF)break;
    }
 
    for(int i=1;i<=MAXN;i++){
        dp[i]=add(dp[i-1],(ll)( add(add(add(pre[i-1],1),pre[i-1]),a[i]) )*a[i]%MOD*i%MOD*val%MOD);
        pre[i]=add(pre[i-1],a[i]);
    }
 
    int t;scanf("%d",&t);
    while(t--){
        int n;scanf("%d",&n);
        int l=1,r=MAXN;
        int pos;
        while(l<=r){
            int mid=l+r>>1;
            if(n<=sum[mid]){
                pos=mid;
                r=mid-1;
            }
            else l=mid+1;
        }
        int x=n-sum[pos-1];
        int ans=add(dp[pos-1],(ll)( add(add(add(pre[pos-1],1),pre[pos-1]),x) )*x%MOD*pos%MOD*val%MOD);
        printf("%d
",ans);
    }
    return 0;
}

 

以上是关于Aggregated Counting(找规律 + 预处理)的主要内容,如果未能解决你的问题,请参考以下文章

PAT 甲级 1049 Counting Ones (30 分)(找规律,较难,想到了一点但没有深入考虑嫌麻烦)***

338. Counting Bits (Binary)

C. Yet Another Counting Problem(循环节规律)

1049 Counting Ones (30 分)难度: 难 / 知识点: 分治 / DP

leetcode 338. Counting Bits,剑指offer二进制中1的个数

338. Counting Bits_比特位计数_简单动态规划