A
給定長度爲n的序列a,求有多少對i,j(i<j),使得∣ai−aj∣ mod b=c
若干組數據(大概5組)。 每組數據第一行三個整數n(1≤n≤100),b,c(0≤c<b≤109)。 接下來一行n個整數ai(0≤ai≤109)。
對於每組數據,輸出一行表示答案。
3 3 2 1 2 3 3 3 1 1 2 3
1 2
按照題目要求,枚舉任意兩個數檢查是否符合題意。
值得注意的是一開始所有數先對b取模這個方法是錯誤的。
#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
給定長度爲n的序列bi,求有多少長度爲k的本質不同的上升子序列。 設該序列位置爲a1,a2...ak一個序列爲上升子序列,當且僅當a1<a2<...<ak且ba1<ba2<...<bak。 本質不同當且僅當兩個序列a和A存在一個i使得ai≠Ai。
若干組數據(大概5組)。 每組數據第一行兩個整數n(1≤n≤100),k(1≤k≤n)。 接下來一行n個整數bi(0≤bi≤109)。
對於每組的每個詢問,輸出一行。
3 2 1 2 2 3 2 1 2 3
2 3我們可以通過dp[i][j]表示第i個數,當前這個數爲序列中的第j個數的方案總數。 轉移爲dp[i][j]=sumdp[k][j−1](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
給定n∗m(n+m爲奇數)的矩陣,從(1,1)走到(n,m)且只能往右往下走,設經過的數爲a1,a2...a2k,貢獻爲a1∗a2+a3∗a4+...+a2k−1∗a2k,求最小貢獻。
若干組數據(大概5組)。 每組數據第一行兩個數n,m(1≤n,m≤1000且n+m爲奇數)。 接下來n行每行m個數ai,j(1≤ai,j≤100)描述這個矩陣。
對於每組數據,輸出一行表示答案。
2 3 1 2 3 2 2 1 2 3 2 2 1 1 2 4
4 8令dp[i][j]表示當前走到第i,j個位置的最小貢獻,我們可以假定(i+j)爲奇數,由該狀態可以轉移向最多4個位置,就可以了。
#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;
}