• AtCoder Grand Contest 009 E:Eternal Average


    题目传送门:https://agc009.contest.atcoder.jp/tasks/agc009_e

    题目翻译

    纸上写了(N)(1)(M)(0),你每次可以选择(k)个数字擦掉,然后再写一个他们的平均值上去。保证(N+M-1)可以整除(k-1),请问最后留下来的那个数有多少种。(N,M,Kleqslant 2000)

    题解

    这题可以转化一下题意:有一棵(k)叉树,有(n+m)个叶子,每个叶子的权值是(0)(1),其他结点的权值是子结点权值的平均值。问根节点的权值有多少种情况。

    假设权值为(0)的叶子的深度分别为(x_i),权值为(1)的叶子的深度分别为(y_i)

    显然:(sum k^{-x_i}+sum k^{-y_i}=1)

    所以对于所有的有理数(s),根的权值可能等于他必然满足:

    (s=sum k^{-y_i})

    (1-s=sum k^{-x_i})

    (s)写成(k)进制(0.s_1s_2s_3...s_{len}),如果(s)可以被(N)(k^{-1})的幂的和表示,那么一定满足:

    (sumlimits_{i=1}^{len}s_ileqslant N)(sumlimits_{i=1}^{len}s_iequiv N(mod k-1))

    我们还可以把(k^{-a})拆成(k)(k^{-a-1})来凑出恰好(N)

    然后我们就可以(N^2dp)(s)的方案数了。

    时间复杂度:(O(nm))

    空间复杂度:(O(nm))

    代码如下:

    #include <cstdio>
    #include <algorithm>
    using namespace std;
     
    const int maxn=2e3+5,pps=1e9+7;
     
    int n,m,k,ans,len;
    int f[maxn<<1][maxn];
     
    int read() {
    	int x=0,f=1;char ch=getchar();
    	for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
    	for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
    	return x*f;
    }
     
    int main() {
    	n=read(),m=read(),k=read();
    	len=(n+m-1)/(k-1);
    	for(int i=1;i<k;i++)
    		f[1][i]=1;
    	for(int i=2;i<=len;i++)
    		for(int j=1;j<=n;j++) {
    			f[i][j]=(f[i-1][j]+f[i][j-1])%pps;
    			if(j>=k)f[i][j]=(f[i][j]+pps-f[i-1][j-k])%pps;
    		}
    	for(int i=1;i<=len;i++) {
    		int limit=max(0,i*(k-1)-m)+1;
    		for(int j=n;j>=limit;j-=k-1)
    			ans=(ans+f[i][j])%pps;
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    【Docker】 CentOS7 安装 Docker 及其使用方法 ( 一 )
    js加密解密
    JSON.parse和eval()的区别
    复选框(全选/全不选/反选)
    圆形进度条
    C# JToken类,实现解析动态json数据、遍历、查找
    使IIS服务器支持下载 apk/ipa 安装包
    Python关键字
    C#泛型(二)泛型类
    C#泛型(一)泛型方法
  • 原文地址:https://www.cnblogs.com/AKMer/p/10191091.html
Copyright © 2020-2023  润新知