【NOIP2016提高A组模拟10.15】算循环
(File IO): input:loop.in output:loop.out
Time Limits: 1000 ms Memory Limits: 524288 KB
Description
Input
Output
Sample Input
167 198
Sample Output
906462341
Data Constraint
解题思路(我的)
首先我们可以将题目所求写成这样的形式:
∑i=1n∑j=1m∑k=1n∑l=1m∑x=ik∑y=jl1
20分:call题目上的标O(n^6)
40分:
首先我们可以知道:
∑i=x1y1∑j=x2y2f(i)∗g(j)=(∑i=x1y1f(i))∗(∑j=x2y2g(j))
(这很显然啊)
于是公式化为
∑i=1n∑j=1m∑k=1n−i+1∑l=1m−j+1∑x=1k∑y=1l1
—–>
∑i=1n∑j=1m∑k=1n−i+1∑l=1m−j+1kl
O(n^4)枚举
60分:
你要会逆元
很明显公式又可以化为
∑i=1n∑j=1m(∑k=1n−i+1k)∗(∑l=1m−j+1l)
—–>
∑i=1n∑j=1m(n−i+2)∗(n−i+1)2∗(m−j+2)∗(m−j+1)2
—–>
∑i=1n∑j=1m(n−i+2)∗(n−i+1)∗(m−j+2)∗(m−j+1)4
—–>
∑ni=1∑mj=1(n−i+2)∗(n−i+1)∗(m−j+2)∗(m−j+1)4
—–>
∑ni=1∑mj=1(n2−2ni+3n+i2−3i+2)∗(m2−2mj+3m+j2−3j+2)4
O(n^2)解决
80分:
再将公示转化得到
(∑ni=1(n2−2ni+3n+i2−3i+2))∗(∑mj=1(m2−2mj+3m+j2−3j+2))4
O(n)解决
100分:
有八十分的思路还想不到100的?除非你不会用公式……
有
∑i=1ni=(1+i)∗i/2
∑i=1ni2=n∗(n+1)∗(2n+1)/6
原式化为
(n3−n2(n+1)+3n2+(2n+1)(n+1)n6−32(n+1)n+2n)∗(m3−m2(m+1)+3m2+(2m+1)(m+1)m6−32(m+1)m+2m)4
—–>
(n3−n3−n2+3n2+13n3+12n2+16n−frac32n2−frac32n+2n)∗(m3−m3−m2+3m2+13m3+12m2+16m−frac32m2−frac32m+2m)4
—–>
(13n3+n2+23n)∗(13m3+m2+23m)4
—–>
(n3+3n2+2n)∗(m3+3m2+2m)36
O(1)解决
codes:
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const long long maxn=1e9+7;
long long n,m;
long long get(long long x,long long y)
{
long long ans=1;
while(y)
{
if(y&1)
{
ans=(ans*x)%maxn;
}
x=(x*x)%maxn;
y>>=1;
}
return ans;
}
long long Get(long long x)
{
return((x*x)%maxn*x%maxn+3*x*x%maxn+2*x%maxn)%maxn;
}
int main()
{
freopen("loop.in","r",stdin);
freopen("loop.out","w",stdout);
scanf("%lld%lld",&n,&m);
long long x=Get(n%maxn),y=Get(m%maxn);
printf("%lld",(x*y%maxn)*get(36,maxn-2)%maxn);
}