ACM-ICPC-ChinaFinal-H题

5 篇文章 0 订阅

2016-ChinaFinal-H

题目链接

题意:
给出n,m,k,在n*m的网格内填[1,k]的整数,定义一个格子是great的,如果满足填在这个格子中的数是本行和本列中严格的最大值。定义Ag为网格中恰好有g个great格子的填法数,求Σ(g+1)Ag。

参考博客
题解:
好像可以用组合数学的容斥原理计算,不过上诉博客的做法我觉得思维性很强,想清楚后很简单,就是一个快速幂。

做法是观察整体,把问题转化成每个位置是great格子对最终答案的贡献和,这样就绕开了Ag的计算。(不知道怎么想到的)

如何绕开Ag的计算? 其实就是Σ(g+1)Ag = Σg*Ag+ΣAg。有点思维性的来了,这里ΣAg其实就等于整体填数法(K^(M*N))。仔细想象很容易理解,就是每种填数法对应于ΣAg中的一种情况。

接下来的问题就是Σg*Ag的计算了,这个思维性更强。用贡献和的思想转化,因为有g个great格的填法数乘了个g相当于摊到了这g个位置上,也就是说每个great格独立了,也即每一个格是great格对Σg*Ag贡献=使这个格是great的所有填法总数:Contrib=Σ(i=1到i=K-1)i^(N-1+M-1)×K^[(N-1)×(M-1)] 。(什么鬼其实我也不太懂,懂的同学麻烦评论让大家学习学习)
我们这样想想,假设3个great格的Ag=2,那么每个Ag里面的三个great格的对应的填法加起来后刚好就是3*2,类推每个格子的great填法加起来就是Σg*Ag。

这里注意一点:以上公式没有考虑n=m=1的情况,因为这时填任意数也算是great格。

代码如下:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
using namespace std;

typedef long long ll;
ll n,m,k;
ll mod = 1e9+7;

ll pow_mod(ll a,ll b)
{
    ll ans = 1;
    while(b)
    {
        if(b&1) ans = (ans*a)%mod;
        a = (a*a)%mod;
        b >>= 1;
    }
    return ans;
}

int main()
{
    int t;
    ll ans;
    scanf("%d",&t);
    for(int ca=1;ca<=t;ca++)
    {
        ans = 0;
        scanf("%lld%lld%lld",&n,&m,&k);
        for(ll i=1;i<k;i++)
        {
            ans = (ans+pow_mod(i,n+m-2))%mod;
        }
        ans = ans*pow_mod(k,(n-1)*(m-1))%mod;
        ans = ans*n%mod*m%mod;
        ans = (ans+pow_mod(k,m*n))%mod;
        if(n==1&&m==1) ans=(ans+1)%mod;
        printf("Case #%d: %lld\n",ca,ans);
    }
    return 0;
}

这里不知道什么鬼,我把n,m,k写成int时是错的,我觉得快速幂的时候应该不会爆int啊。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值