天天看點

補幾道題

一直忙着複習,是以好久好久沒寫題解了。

暑假集訓開始了,開始寫題解吧,順便有自己的一個計劃,會在部落格中展現的:

cf #240 div2 D

D. Mashmokh and ACM

Mashmokh’s boss, Bimokh, didn’t like Mashmokh. So he fired him. Mashmokh decided to go to university and participate in ACM instead of finding a new job. He wants to become a member of Bamokh’s team. In order to join he was given some programming tasks and one week to solve them. Mashmokh is not a very experienced programmer. Actually he is not a programmer at all. So he wasn’t able to solve them. That’s why he asked you to help him with these tasks. One of these tasks is the following.

A sequence of l integers b1, b2, …, bl (1 ≤ b1 ≤ b2 ≤ … ≤ bl ≤ n) is called good if each number divides (without a remainder) by the next number in the sequence. More formally for all i (1 ≤ i ≤ l - 1).

Given n and k find the number of good sequences of length k. As the answer can be rather large print it modulo 1000000007 (109 + 7).

Input

The first line of input contains two space-separated integers n, k (1 ≤ n, k ≤ 2000).

Output

Output a single integer — the number of good sequences of length k modulo 1000000007 (109 + 7).

input

3 2

output

5

題意: 就是說輸入n,k; 問你在1-n中 長度為k的有效序列有多少個, 有效序列的定義 就是 非遞減序列,1<=ai<=n 且ai+1 % ai ==0, 也就是每一個序列中的數都是前一個的整數倍。

分析: 這種題目需要我們慢慢推理: 不能急也不能慌,感覺上是肯定能做的。

首先 這個序列 自然是與n息息相關, 自然和長度k 也有關系。

而且 n 和n-1 的序列必然也是 有關系的, 由此我們細想一會兒不難想到是狀态的轉移,既然想到這方面必然就得思考怎麼建立dp與轉移方程。

不妨設 dp[i ][ j ]代表 以i為結尾的 長度為j的最大值; 那麼想想若是i,j+1 呢? 我們可以在原來的長度為j的後面加一個i即可, 說明 dp[i][j+1] >=dp[i][j]。 那麼i 的整數倍 也是如此:dp[i*k][j+1]>dp[i][j];

不難得到結果;

int main()
{
    //freopen("1.txt","r",stdin);
    int n,k;
    scanf("%d %d",&n,&k);
    for(int i=1;i<=n;i++) //所有長度為1,以i結尾的都一種
        dp[i][1]=1;
    for(int j=1;j<k;j++){
       for(int i=1;i<=n;i++){
         if(dp[i][j])
           for(int len=i;len<=n;len+=i){
               //長度為j+1,以 i的倍數   結尾的必然包含長度為j 以i結尾的種數
               // 因為在後面加上一個i的倍數 即可
               dp[len][j+1]+=dp[i][j],dp[len][j+1]%=MOD;

           }
       }
    }
    int ans=0;
    for(int i=1;i<=n;i++){  //所有長度為k的,以1-n結尾的
        ans+=dp[i][k],ans%=MOD;
    }
    printf("%d\n",ans);
    return 0;
}           

一場GYM 試試手而已,最後還是沒有AK

2016 Al-Baath University Training Camp Contest-1 I. March Rain

題意:

由一串序列1-n來表示屋頂,在這個屋頂上會給你洞,然後你最多使用k塊闆子, 每一塊闆子的長度都可以自由更改,可以不同,然後問闆子中 最長的闆子 最小值是多少?

最小化最大值,咋一想覺得是貪心,但是最後20+分鐘想了一會兒貪心覺得想不出來, 往正解上想到了,但是并沒有時間敲and debug了。 其實二分也可以看成一種貪心, 我們隻需要二分闆子的長度(1-1e9),然後判斷在這個長度下,闆子夠不夠用即可

using namespace std;
int pos[1000005];
int p[1000005];
int work(int n,int len){
    int cnt=0;
    int ans=0;
    for(int i=1;i<=n;i++){
        if(pos[i]>cnt){
//          printf("dong =%d ",pos[i]);
            ans++;
            cnt=pos[i]+len-1;
//          printf("%d %d\n",cnt,pos[i]);
        }
    }
    return ans;
}
int main(){
    int t;
    //freopen("1.txt","r",stdin);
    scanf("%d",&t);
    while(t--){
        int n,k;
        scanf("%d %d",&n,&k);
        for(int i=1;i<=n;i++)
            scanf("%d",&pos[i]);
        int l=1;
        int r=pos[n];
        while(l<r){
            int mid=(l+r)/2; //現在長度為mid
//          printf("%d %d %d\n",l,r,work(n,mid));
            if(work(n,mid)> k){  //長度不夠,需要>cnt塊
                l=mid+1;
            }
            else
                r=mid;
        }
        printf("%d\n",l);
    }
return 0;
}           

J X and Beasts

這個題就是一個最大遞增子序列問題,不是最長而是最大,由于n*n可以過,就随便寫了寫

using namespace std;
int f[1000005];
int x[105],y[105];
void work(){
    mem(f);
    for(int i=2;i<=1000000;i*=2){
        for(int j=1;j*i<=1000000;j++){
            f[i*j]++;
        }
    }
//  for(int i=1;i<=100;i++){
//      printf("%d %d\n",i,f[i]);
//  }
}
int dp[105];
int main(){
    //freopen("1.txt","r",stdin);
    work();
    int t;
    scanf("%d",&t);
    while(t--){
        int n;
        int sum=0;
        scanf("%d",&n);
        int pre=0;
        for(int i=1;i<=n;i++){
             scanf("%d",&x[i]);
             //x[i]=f[x[i]];
        }
        for(int i=1;i<=n;i++){
            int maxn=0;
            for(int j=i-1;j>=1;j--){
                if(x[i]>x[j]){
                    maxn=max(maxn,dp[j]);
                }
            }
            dp[i]=f[x[i]]+maxn;

        }
        for(int i=1;i<=n;i++)
            sum=max(sum,dp[i]);
        printf("%d\n",sum);
    }
return 0;
}