当前位置: 首页 > article >正文

【Codeforces】 CF582D Number of Binominal Coefficients

题目链接

CF方向
Luogu方向

题目解法

看到 p α ∣ ( n k ) p^{\alpha} | \binom{n}{k} pα(kn) ,首先想到 k u m m e r kummer kummer 定理,那么限制即为 n − k n-k nk k k k 做加法在 p p p 进制下的进位数 ≥ α \ge \alpha α
然后就是一个显然的数位 d p dp dp
因为进位从前往后数位 d p dp dp 不太好考虑,所以我们考虑从后往前做,然后多记录一维 0 / 1 / 2 0/1/2 0/1/2
我的状态是 f i , j , 0 / 1 , 0 / 1 / 2 f_{i,j,0/1,0/1/2} fi,j,0/1,0/1/2 表示后 i i i 位有 j j j 个进位(不包括第 i i i 位的),这一位是否进位,后面 i i i n n n A A A 的关系(0 表示 n < A n<A n<A,1 表示 n = A n=A n=A,2 表示 n > A n>A n>A
因为我们把 n , k n,k n,k 变成了 n − k n-k nk k k k,所以天然保证了 n ≥ k n\ge k nk,不需要考虑 n , k n,k n,k 的大小关系
直接 d p dp dp 即可,实现的有些烦,但也不知道可以优化什么了
时间复杂度 O ( n 2 ) O(n^2) O(n2)

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=4100,P=1e9+7;
int p,a,f[2][N][2][3];
LL A[N],B[N];
// int g[P];//g[i]表示a+b<=i的方案数(a,b无序)
char str[N];
inline int read(){
    int FF=0,RR=1;
    char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') RR=-1;
    for(;isdigit(ch);ch=getchar()) FF=(FF<<1)+(FF<<3)+ch-48;
    return FF*RR;
}
inline void inc(int &x,LL y){ x=(x+y)%P;}
int g(int x){
    if(x<0) return 0;
    if(x<p) return (1ll*(x+2)*(x+1)/2)%P;
	x=p*2-1-x;x=1ll*p*p%P-(1ll*x*(x-1)/2)%P;
	return x<0?x+P:x;
}
int main(){
    p=read(),a=read();
    scanf("%s",str+1);
    int len=strlen(str+1);
    for(int i=1;i<=len;i++) A[i]=str[len-i+1]-48;
    int n=0;
    for(int i=len;i>=1;i--){
        for(int j=1;j<N;j++) B[j]*=10;
        B[1]+=A[i];
        for(int j=1;j<N;j++) if(B[j]>=p) B[j+1]+=B[j]/p,B[j]%=p;
    }
    for(int i=1;i<N;i++) A[i]=B[i];
    for(int i=1;i<N;i++) if(A[i]) n=i;
    reverse(A+1,A+n+1);
    f[(n+1)&1][0][0][1]=1;
    for(int i=n+1;i>1;i--){
        int c=A[i-1];
        int g_c=g(c);
        int g_c_1=g(c-1);
        int g_c_2=g(c-2);
        int g_p_1=g(p-1);
        int g_p_2=g(p-2);
        int g_p_c=g(p+c);
        int g_p_c_1=g(p+c-1);
        int g_p_c_2=g(p+c-2);
        int g_2p_2=g(p*2-2);
        int g_2p_3=g(p*2-3);
        memset(f[~i&1],0,sizeof(f[~i&1]));
        for(int j=0;j<=n-i+1;j++){
            //calc f[~i&1][j][0][0]
            inc(f[~i&1][j][0][0],1ll*f[i&1][j][0][0]*g_c);
            if(c){
                for(int t:{1,2}) inc(f[~i&1][j][0][0],1ll*f[i&1][j][0][t]*g_c_1);
                if(j){
                    inc(f[~i&1][j][0][0],1ll*f[i&1][j-1][1][0]*g_c_1);
                    if(c>1) for(int t:{1,2}) inc(f[~i&1][j][0][0],1ll*f[i&1][j-1][1][t]*g_c_2);
                }
            }
            //calc f[~i&1][j][0][1]
            if(!c) inc(f[~i&1][j][0][1],1ll*f[i&1][j][0][1]*g_c);
            else inc(f[~i&1][j][0][1],1ll*f[i&1][j][0][1]*(g_c-g_c_1+P));
            if(j&&c) inc(f[~i&1][j][0][1],1ll*f[i&1][j-1][1][1]*(g_c_1-g_c_2+P));
            //calc f[~i&1][j][0][2]
            for(int t:{0,1}) inc(f[~i&1][j][0][2],1ll*f[i&1][j][0][t]*(g_p_1-g_c+P));
            inc(f[~i&1][j][0][2],1ll*f[i&1][j][0][2]*(g_p_1-g_c_1+P));
            if(j){
                for(int t:{0,1}) inc(f[~i&1][j][0][2],1ll*f[i&1][j-1][1][t]*(g_p_2-g_c_1+P));
                inc(f[~i&1][j][0][2],1ll*f[i&1][j-1][1][2]*(g_p_2-g_c_2+P));
            }
            //calc f[~i&1][j][1][0]
            inc(f[~i&1][j][1][0],1ll*f[i&1][j][0][0]*(g_p_c-g_p_1+P));
            for(int t:{1,2}) inc(f[~i&1][j][1][0],1ll*f[i&1][j][0][t]*(g_p_c_1-g_p_1+P));
            if(j){
                inc(f[~i&1][j][1][0],1ll*f[i&1][j-1][1][0]*(g_p_c_1-g_p_2+P));
                for(int t:{1,2}) inc(f[~i&1][j][1][0],1ll*f[i&1][j-1][1][t]*(g_p_c_2-g_p_2+P));
            }
            //calc f[~i&1][j][1][1]
            inc(f[~i&1][j][1][1],1ll*f[i&1][j][0][1]*(g_p_c-g_p_c_1+P));
            if(j) inc(f[~i&1][j][1][1],1ll*f[i&1][j-1][1][1]*(g_p_c_1-g_p_c_2+P));
            //calc f[~i&1][j][1][2]
            for(int t:{0,1}) inc(f[~i&1][j][1][2],1ll*f[i&1][j][0][t]*(g_2p_2-g_p_c+P));
            inc(f[~i&1][j][1][2],1ll*f[i&1][j][0][2]*(g_2p_2-g_p_c_1+P));
            if(j){
                for(int t:{0,1}) inc(f[~i&1][j][1][2],1ll*f[i&1][j-1][1][t]*(g_2p_2-g_p_c_1+P));
                inc(f[~i&1][j][1][2],1ll*f[i&1][j-1][1][2]*(g_2p_2-g_p_c_2+P));
            }
        }
    }
    int ans=0;
    for(int i=a;i<=n;i++) inc(ans,1ll*f[1][i][0][0]+f[1][i][0][1]);
    printf("%d\n",ans);
    fprintf(stderr,"%d ms\n",int(1e3*clock()/CLOCKS_PER_SEC));
    return 0;
}
/*
f[i][j][0/1][0/1/2]:到第i位,后j位已经填好且进位了j次,这一位是否进位,n后面j位和A的关系(0小于,1等于,2大于)
*/


http://www.kler.cn/news/107829.html

相关文章:

  • 浅谈 MySQL 主从复制,优点?原理?
  • Spring Security漏洞防护—HttpFirewall和 HTTPS
  • StripedFly恶意软件框架感染了100万台Windows和Linux主机
  • 0基础学习PyFlink——用户自定义函数之UDTAF
  • Git 拉取远程更新报错
  • Linux音频-基本概念
  • 记录--vue3实现excel文件预览和打印
  • NewStarCTF2023week4-Nmap
  • 【华为OD:C++机试】Day-1
  • 已解决:conda找不到对应版本的cudnn如何解决?
  • K8s 部署 CNI 网络组件+k8s 多master集群部署+负载均衡
  • 猴子吃桃问题--C语言
  • 计算机操作系统重点概念整理-第五章 文件管理【期末复习|考研复习】
  • 不再受害:如何预防和应对.mallab勒索病毒攻击
  • Mac运行Docker报错
  • shell实现部署ftp提供共享yum仓库
  • QT中获取当前项目路径的写法
  • 已有wchar_t *类型的filepath,使用Qt打开该文件
  • CLIP文章精读
  • 【计算机毕设经典案例】基于微信小程序的图书管理系统
  • 水性杨花:揭秘CSS响应式界面设计,让内容灵活自如,犹如水之变幻
  • synchronized 的锁类型
  • 使用mac自带VNC公网远程控制macOS
  • [备忘.Linux]服务部署管理常用命令|systemd
  • JS条件表达式
  • [Python] OSError: [E050] Can‘t find model ‘en_core_web_sm‘.
  • 实用篇-认识微服务
  • stable-diffusion-ui 下载和安装
  • 【uniapp】仿微信支付界面
  • Day 46 动态规划 part12