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;
}