338. 计数问题 - AcWing题库
还是不会。。。
1081. 度的数量 - AcWing题库
其实就是把一个数n转化成B进制的数x,例如x = 654321,那么我们要找的就是在小于x的数里面,在它们的各个位置上填0和1,满足K个1,其他数都是0
import java.util.*;
public class Main{
static int N = 35;
static int[][] f = new int[N][N];//组合数,f[i][j]表示从i个点中选j个点的方案数
static int X, Y, K, B;
//预处理组合数,数组f
public static void init(){
for(int i = 0; i < N; i ++){
for(int j = 0; j <= i; j ++){
if(j == 0) f[i][j] = 1;
else f[i][j] = f[i - 1][j - 1] + f[i - 1][j];
}
}
}
public static int dp(int n){
if(n == 0) return 0;//先判断边界
List<Integer> list = new ArrayList<>();
while(n != 0){//将这个数分解为B进制的数
list.add(n % B);
n /= B;
}
int res = 0;//答案
int last = 0;//前缀信息,已经用了多少个1
for(int i = list.size() - 1; i >= 0; i --){
int x = list.get(i);
if(x != 0){
//x大于1和等于1的时候,枚举到的第i位都可以取0,所以剩下的1在剩下的i位数中选(因为最低位的下标为0)
//x大于等于1,第i位选0
res += f[i][K - last];
//x大于1,第i位选1
//后面的其他位可以随便取
if(x > 1){//-1是因为第i位选1,所以剩下可选的就少1
if(K - last - 1 >= 0) res += f[i][K - last - 1];
break;
}
//x等于1,第i位选1
else{
last ++;
if(last > K) break;//不合法,直接break
}
}
if(i == 0 && K == last) res ++;
}
return res;
}
//开始main函数
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
X = sc.nextInt();
Y = sc.nextInt();
K = sc.nextInt();
B = sc.nextInt();
init();//预处理
System.out.print(dp(Y) - dp(X - 1));//技巧一
}
}
1082. 数字游戏 - AcWing题库
import java.util.*;
public class Main{
static int N = 15;
static int[][] f = new int[N][10];
static int l, r;
public static void init(){
for(int i = 0; i <= 9; i ++){
f[1][i] = 1;//只有一位数
}
for(int i = 2; i < N; i ++){
for(int j = 0; j <= 9; j ++){
for(int k = j; k <= 9; k ++){
f[i][j] += f[i - 1][k];//由公式推出
}
}
}
}
public static int dp(int n){
if(n == 0) return 1;
List<Integer> list = new ArrayList<>();
while(n != 0){
list.add(n % 10);
n /= 10;
}
int res = 0;//答案
int last = 0;//上一位的最大数值
for(int i = list.size() - 1; i >= 0; i --){
int x = list.get(i);
//枚举左枝的情况
for(int j = last; j < x; j ++){
res += f[i + 1][j];
}
//如果上一个数last比x大,就直接退出
if(last > x) break;
else last = x;
if(i == 0) res ++;
}
return res;
}
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
init();//初始化
while(sc.hasNext()){
int l = sc.nextInt();
int r = sc.nextInt();
System.out.println(dp(r) - dp(l - 1));
}
}
}
1083. Windy数 - AcWing题库
import java.util.*;
public class Main{
static int N = 15;
static int[][] f = new int[N][10];//f[i][j]表示一共有i位数,最高位是j的所有表示方案
static int l, r;
public static void init(){
for(int i = 0; i <= 9; i ++) f[1][i] = 1;
for(int i = 2; i < N; i ++){
for(int j = 0; j <= 9; j ++){
for(int k = 0; k <= 9; k ++){
//相差至少为2
if(Math.abs(j - k) >= 2) f[i][j] += f[i - 1][k];
}
}
}
}
public static int dp(int n){
if(n == 0) return 0;
List<Integer> list = new ArrayList<>();
while(n != 0){
list.add(n % 10);
n /= 10;
}
int res = 0;
int last = -2;//要保证last和0-9的每一个数都要至少相差2,因为要保证第一位随便取
for(int i = list.size() - 1; i >= 0; i --){
int x = list.get(i);
for(int j = (i == list.size() - 1 ? 1 : 0); j < x; j ++){
if(Math.abs(j - last) >= 2) res += f[i + 1][j];
}
if(Math.abs(x - last) >= 2) last = x;
else break;
if(i == 0) res ++;
}
//处理一下前导0的情况
for(int i = 0; i < list.size(); i ++){
//j必须只能从1开始
for(int j = 1; j <= 9; j ++){
res += f[i][j];
}
}
return res;
}
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
l = sc.nextInt();
r = sc.nextInt();
init();
System.out.print(dp(r) - dp(l - 1));
}
}
1084. 数字游戏 II - AcWing题库
import java.util.*;
public class Main{
static int N = 15, M = 110;
static int[][][] f = new int[N][10][M];//f[i][j][k] === 状态表示是:一共有i为数,最高位的数是j,余数是k
static int l, r, P;
//因为java运算中正数取模之后结果是正数,负数取模之后是负数
public static int mod(int a, int b){
return (a % b + b) % b;
}
public static void init(){
for(int i = 0; i < N; i ++){
for(int j = 0; j < 10; j ++){
Arrays.fill(f[i][j], 0);//因为由多组测试数据,所以每次都要初始化
}
}
for(int i = 0; i <= 9; i ++) f[1][i][i % P] = 1;//边界,一位数的情况
for(int i = 2; i < N; i ++){//位数从2开始
for(int j = 0; j <= 9; j ++){//最高位数j
for(int k = 0; k < P; k ++){//余数
for(int x = 0; x <= 9; x ++){//下一位数的最高位
//已知前一位的最高位是j,所有数之和modP的结果为k,那么固定j,剩下的i-1位modP的余数就是(k-j)modP
f[i][j][k] += f[i - 1][x][mod(k - j, P)];
}
}
}
}
}
public static int dp(int n){
if(n == 0) return 1;
List<Integer> list = new ArrayList<>();
while(n != 0){
list.add(n % 10);
n /= 10;
}
int res = 0;//答案
int last = 0;//前面的各位数之和
for(int i = list.size() - 1; i >= 0; i --){
int x = list.get(i);
//左边
for(int j = 0; j < x; j ++){
//前面数的和是last,要想加上后面的数模P等于0,那么后面数的余数就是-lastmodP
res += f[i + 1][j][mod(-last, P)];
}
//每次加x
last += x;
//右边
if(i == 0 && mod(last, P) == 0) res ++;
}
return res;
}
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
l = sc.nextInt();
r = sc.nextInt();
P = sc.nextInt();
init();
System.out.println(dp(r) - dp(l - 1));
}
}
}
1085. 不要62 - AcWing题库
import java.util.*;
public class Main{
static int N = 15;
static int l, r;
static int[][] f = new int[N][10];//f[i][j]表示i位数,最高位为j,且没有4和62
public static void init(){
for(int i = 0; i <= 9; i ++){
if(i != 4) f[1][i] = 1;
}
for(int i = 2; i < N; i ++){
for(int j = 0; j <= 9; j ++){
if(j == 4) continue;
for(int k = 0; k <= 9; k ++){
if(k == 4 || (j == 6 && k == 2)) continue;
f[i][j] += f[i - 1][k];
}
}
}
}
public static int dp(int n){
if(n == 0) return 1;
List<Integer> list = new ArrayList<>();
while(n != 0){
list.add(n % 10);
n /= 10;
}
int res = 0;
int last = 0;
for(int i = list.size() - 1; i >= 0; i --){
int x = list.get(i);
for(int j = 0; j < x; j ++){
if(j == 4 || (last == 6 && j == 2)) continue;
res += f[i + 1][j];//一定要记得这里是i+1位
}
if(x == 4 || (last == 6 && x == 2)) break;
last = x;
if(i == 0) res ++;
}
return res;
}
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
init();//只需要初始化一次
while(true){
l = sc.nextInt();
r = sc.nextInt();
if(l == 0 && r == 0) break;
System.out.println(dp(r) - dp(l - 1));
}
}
}
1086. 恨7不成妻 - AcWing题库
太难了太难了