BestCoder Round #63

A

給定長度爲nn的序列a,求有多少對ijiji,j(i<j),使得∣aiaj∣ mod bcaiaj mod b=c
輸入描述
若干組數據(大概55組)。
每組數據第一行三個整數n1n100bc0cb109n(1n100),b,c(0c<b109)。
接下來一行nn個整數ai0ai109ai(0ai109)
輸出描述
對於每組數據,輸出一行表示答案。
輸入樣例
3 3 2
1 2 3
3 3 1
1 2 3
輸出樣例
1
2

按照題目要求,枚舉任意兩個數檢查是否符合題意。

值得注意的是一開始所有數先對bb取模這個方法是錯誤的。

#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <map>
#include <stack>
#include <queue>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
int a[1000];

int main(){
	int n,b,c;
	while(~scanf("%d",&n)){
		scanf("%d%d",&b,&c);
		for(int i=0;i<n;++i)
			scanf("%d",&a[i]);
		int cnt=0;
		for(int i=0;i<n;++i){
			for(int j=i+1;j<n;++j){
				if(abs(a[i]-a[j])%b==c)
					++cnt;
			}
		}
		printf("%d\n",cnt);
	}	
	return 0;
}

B

給定長度爲nn的序列bibi,求有多少長度爲kk的本質不同的上升子序列。
設該序列位置爲a1a2...aka1,a2...ak一個序列爲上升子序列,當且僅當a1a2...aka1<a2<...<akba1ba2...bakba1<ba2<...<bak。
本質不同當且僅當兩個序列aaAA存在一個ii使得aiAiaiAi
輸入描述
若干組數據(大概55組)。
每組數據第一行兩個整數n1n100k1knn(1n100),k(1kn)。
接下來一行nn個整數bi0bi109bi(0bi109)
輸出描述
對於每組的每個詢問,輸出一行。
輸入樣例
3 2
1 2 2
3 2
1 2 3
輸出樣例
2
3
我們可以通過dpijdp[i][j]表示第ii個數,當前這個數爲序列中的第jj個數的方案總數。 轉移爲dpijsumdpkj1kibkbidp[i][j]=sumdp[k][j1](k<i,bk<bi)。 本題需要高精度。

import java.util.*;
import java.math.*;

class Main{
	public BigInteger ONE=new BigInteger("1");
	public BigInteger zero=new BigInteger("0");
	public static void main(String[] agrs){
		Scanner cin=new Scanner(System.in);
		while(cin.hasNext()){
			int n=cin.nextInt(),m=cin.nextInt();
			int[] a=new int[n];
			BigInteger[][] dp=new BigInteger[n][n+1];
			for(int i=0;i<n;++i)
				a[i]=cin.nextInt();
			for(int i=0;i<n;++i){
				for(int j=0;j<=n;++j){
					dp[i][j]=new BigInteger("0");
				}
				dp[i][1]=new BigInteger("1");
			}
			dp[0][1]=new BigInteger("1");
			BigInteger ans=new BigInteger("0");
			for(int i=1;i<n;++i){
				for(int j=1;j<=m;++j){
					for(int k=0;k<i;++k)
						if(a[k]<a[i])
							dp[i][j]=dp[i][j].add(dp[k][j-1]);
				}
			}
			
			for(int i=m-1;i<n;++i)
				ans=ans.add(dp[i][m]);
			System.out.println(ans);
		}
	}
}

C

給定nmnm(nmn+m爲奇數)的矩陣,從11(1,1)走到nm(n,m)且只能往右往下走,設經過的數爲a1a2...a2ka1,a2...a2k,貢獻爲a1a2a3a4...a2k1a2ka1a2+a3a4+...+a2k1a2k,求最小貢獻。
輸入描述
若干組數據(大概55組)。
每組數據第一行兩個數nm1nm1000n,m(1n,m1000nmn+m爲奇數)。
接下來nn行每行mm個數aij1aij100ai,j(1ai,j100)描述這個矩陣。
輸出描述
對於每組數據,輸出一行表示答案。
輸入樣例
2 3
1 2 3
2 2 1
2 3
2 2 1
1 2 4
輸出樣例
4
8
dpijdp[i][j]表示當前走到第iji,j個位置的最小貢獻,我們可以假定ij(i+j)爲奇數,由該狀態可以轉移向最多44個位置,就可以了。

#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <map>
#include <stack>
#include <queue>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
long long a[1005][1005];
long long dp[1005][1005];

int main(){
    int n,m;
    while(~scanf("%d%d",&n,&m)){
        for(int i=0;i<n;++i){
            for(int j=0;j<m;++j)
                scanf("%lld",&a[i][j]);
        }
        memset(dp,0,sizeof(dp));
        for(int i=0;i<n;++i)
            for(int j=0;j<m;++j)
                dp[i][j]=1LL<<33;
        dp[0][0]=0;
        for(int i=0;i<n;++i){
            for(int j=0;j<m;++j){
                if(!i && !j)
                    continue;
                if(j){
                    if((i+j)&1){
                        dp[i][j]=min(dp[i][j],dp[i][j-1]+a[i][j-1]*a[i][j]);
                    }
                    else{
                        dp[i][j]=min(dp[i][j],dp[i][j-1]);
                    }
                }
                if(i){
                    if((i+j)&1){
                        dp[i][j]=min(dp[i][j],dp[i-1][j]+a[i-1][j]*a[i][j]);
                    }
                    else{
                        dp[i][j]=min(dp[i][j],dp[i-1][j]);
                    }
                }
            }
        }
        printf("%lld\n",dp[n-1][m-1]);
    }	
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章