ACdream1139 Sum(推公式+逆元求解)

题目链接:http://acdream.info/problem?pid=1139

题意:

给定一个由0~9组成的矩阵,我们求行相邻的组成的数与列相邻的组成的数的和。

eg:

123

456

789

第一行组成的数有 1,2,3,12,23,123

第一列组成的数有 1,4,7,12,47,147.

暴力枚举所有的数肯定是不可取的,我们试着总结。

我们发现a[x][y]在行里出现的数对以后和的贡献为   x*a[x][y]sigma(10 ^(n-i)) (k<=x<=n)

同理a[x][y]在列里出现的数对以后和的贡献为   y*a[x][y]sigma(10 ^(n-i)) (y<=x<=n)

我们设sum[x]表示第x行与第x列的数的和 然后对以上的公式进行合并

sum = sigma( i * sum[i] * ( sigma(10^k)(i<=k<=n)))(1<=i<=n)

sigma(10^k)(i<=k<=n)用到等比数列求和,有除法,需要用到逆元

a/b (mod c)  ==  a (mod b*c)/c

或者 a*~b (mod c)

代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#define PB push_back
#define MP make_pair
#define REP(i,n) for(int i=0;i<(n);++i)
#define FOR(i,l,h) for(int i=(l);i<=(h);++i)
#define DWN(i,h,l) for(int i=(h);i>=(l);--i)
#define IFOR(i,h,l,v) for(int i=(h);i<=(l);i+=(v))
#define CLR(vis) memset(vis,0,sizeof(vis))
#define MST(vis,pos) memset(vis,pos,sizeof(vis))
#define MAX3(a,b,c) max(a,max(b,c))
#define MAX4(a,b,c,d) max(max(a,b),max(c,d))
#define MIN3(a,b,c) min(a,min(b,c))
#define MIN4(a,b,c,d) min(min(a,b),min(c,d))
#define PI acos(-1.0)
#define INF 1000000000
#define LINF 1000000000000000000LL
#define eps 1e-8
#define LL long long
using namespace std;

const int maxn = 1010;
const LL mod = 1e9+7;

char a[maxn][maxn];
LL sum[maxn];

LL multi(LL a,LL b){
    LL ans = 0;
    while(b){
        if(b&1) ans=(ans+a)%mod;
        b>>=1;
        a=(a+a)%mod;
    }
    return ans;
}

LL quick_mod(LL a,LL b){
    LL ans = 1;
    while(b){
        if(b&1) ans=multi(ans,a);
        b>>=1;
        a=multi(a,a);
    }
    return ans;
}

int main()
{
    int n;
    while(~scanf("%d",&n)){
        REP(i,n) scanf("%s",a[i]);
        CLR(sum);
        REP(i,n) REP(j,n) sum[i]=sum[i]+a[j][i]-'0'+a[i][j]-'0';
        LL ans=0;
        LL M = quick_mod(9LL,mod-2);
        REP(i,n){
            LL t = (quick_mod(10,n-i)+mod-1)%mod;
            t=multi(t,M);
            t=multi(sum[i],t);
            ans=(ans+multi(i+1,t))%mod;
        }
        printf("%lld\n",ans);
    }
    return 0;
}
时间: 2024-10-09 20:31:28

ACdream1139 Sum(推公式+逆元求解)的相关文章

hdu 6128 Inverse of sum(推公式)

题目链接:hdu 6128 Inverse of sum 题意: 给你n个数,问你有多少对i,j,满足i<j,并且1/(ai+aj)=1/ai+1/aj 在%p意义下. 题解: 不愧是高中生,推公式神题. 将式子通分化简后可得(ai2+aj2+ai*aj)%p=0. 然后两边同时将两边乘(ai-aj),化简可得(ai3-aj3)%p=0. 然后就可以用map记录一下个数,并且减掉ai==aj时不合法的情况就行了. 1 #include<bits/stdc++.h> 2 #define F

2017多校第7场 HDU 6128 Inverse of sum 推公式或者二次剩余

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6128 题意:给你n个数,问你有多少对i,j,满足i<j,并且1/(ai+aj)=1/ai+1/aj 在%p意义下. 解法:官方题解说是用二次剩余来解,但是我并不会这玩意了.在网上看到一位大佬没有二次剩余直接通过推公式做出了这题,真是神奇.http://www.cnblogs.com/bin-gege/p/7367337.html  将式子通分化简后可得(ai2+aj2+ai*aj)%p=0 .然后两

UVA 10014(推公式)

题目链接:UVA 10014 解题思路: 第一个想法是高斯消元,但貌似复杂度有点高,于是开始推公式,想了好久. 推导过程: a[i-1] + a[i+1] = 2 * ( a[i] + c[i] ) a[1] + a[n] = a[0] + a[n+1] - c[1:n] n = 1, 2, 3, - n (n+1) * a[1] = n*a[0] +a[n+1] - ( n*c[1] + (n-1)*c[2] + - + c[n] ) 代码: #include <cstdio> #inclu

HDU_5734_数学推公式

题意:给一个向量W={w1,w2……,wn},和一个向量B,B的分量只能为1和-1.求||W-αB||²的最小值. 思路:一来一直在想距离的问题,想怎么改变每一维的值才能使这个向量的长度最小,最后无果. 看了题解说是推公式,并且将结果看作是方差,这样W中的负值可直接转化为正值,也即将B所有分量当作1(这里需要想一下),所以只需要看α,当结果为方差时最小,也即α为均值,根据||x||=√∑xi²,将平方项展开,观察思考一下应该可以化解为(n∑wi²-sum²)/n #include<iostrea

hdu 4869 Turn the pokers(递推&amp;组合数学&amp;逆元)

Turn the pokers Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1279    Accepted Submission(s): 466 Problem Description During summer vacation,Alice stay at home for a long time, with nothing t

HDU 4873 ZCC Loves Intersection(JAVA、大数、推公式)

在一个D维空间,只有整点,点的每个维度的值是0~n-1 .现每秒生成D条线段,第i条线段与第i维度的轴平行.问D条线段的相交期望. 生成线段[a1,a2]的方法(假设该线段为第i条,即与第i维度的轴平行)为,i!=j时,a1[j]=a2[j],且随机取区间[0,n-1]内的整数.然后a1[i],a2[i]在保证a1[i]<a2[i]的前提下同样随机. 由于D条线段各自跟自己维度的轴平行,我们可以转换成只求第i个维度与第j个维度的相交期望,然后乘以C(2,n)就好了 显然线段[a1,a2]和线段[

HDU 4870 Rating(概率、期望、推公式) &amp;&amp; ZOJ 3415 Zhou Yu

其实zoj 3415不是应该叫Yu Zhou吗...碰到ZOJ 3415之后用了第二个参考网址的方法去求通项,然后这次碰到4870不会搞.参考了chanme的,然后重新把周瑜跟排名都反复推导(不是推倒)四五次才上来写这份有抄袭嫌疑的题解... 这2题很类似,多校的rating相当于强化版,不过原理都一样.好像是可以用高斯消元做,但我不会.默默推公式了. 公式推导参考http://www.cnblogs.com/chanme/p/3861766.html#2993306 http://www.cn

sgu495:概率dp / 推公式

概率题..可以dp也可以推公式 抽象出来的题目大意: 有 n个小球,有放回的取m次  问 被取出来过的小球的个数的期望 dp维护两个状态 第 i 次取出的是 没有被取出来过的小球的 概率dp[i] 和取出的是已经被取出来过的小球的概率np[i]; 如果第 i-1 次取出的是已经被取出来过的小球 那么第 i 次取出没有取出来过小球的概率即为 dp[i-1]: 反之则为 dp[i-1] - 1/n(没有取出来过的小球少了一个) 所以可以得到状态转移方程 dp[i]=dp[i-1]*(dp[i-1]-

bjfu1211 推公式,筛素数

题目是求fun(n)的值 fun(n)= Gcd(3)+Gcd(4)+…+Gcd(i)+…+Gcd(n).Gcd(n)=gcd(C[n][1],C[n][2],……,C[n][n-1])C[n][k] means the number of way to choose k things from n things. n最大一百万,马上反映到可能是递推打表. 首先肯定是推公式了,fun(n)其实就是Gcd(n)的一个前n项和,没意义,直接看Gcd(n),把前几项列出来,发现公式是Gcd(n) =