6333 Problem B. Harvest of Apples(莫队)
题意
求C(n,m)到C(n,0)的求和
题解
S(n,m)=S(n,m-1)+C(n,m)=S(n-1,m)*2-C(n-1,m)(后面一个根据C(n,m)递推式展开就知道了),由此我们可以用莫队实现,O(1)转移
代码
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<iostream>
#define N 100005
#define mod 1000000007
using namespace std;
typedef long long ll;
ll a[N],pos[N],f[N],inv[N],len;
struct node
{
ll l,r,id;
node(){}
node(ll l,ll r,ll id)
{
this->l=r;
this->r=r;
this->id=id;
}
}q[N];
ll ansa[N];
bool cmp(node a,node b)
{
return pos[a.l]<pos[b.l]||pos[a.l]==pos[b.l]&&a.r<b.r;
}
ll qmi(ll a,ll b)
{
ll ans=1;
while(b)
{
if(b%2)ans=ans*a%mod;
a=a*a%mod;
b/=2;
}
return ans;
}
ll C(ll n,ll m)
{
return f[n]*inv[m]%mod*inv[n-m]%mod;
}
int main()
{
ll n=100000,m,INV=(mod+1)/2;
f[0]=1;
for(ll i=1;i<=n;i++)
f[i]=(f[i-1]*i)%mod;
for(ll i=0;i<=n;i++)
inv[i]=qmi(f[i],mod-2);
scanf("%lld",&m);
len=(ll)sqrt((double)n+0.1);
for(ll i=1;i<=n;i++)
pos[i]=(i-1)/len+1;
for(ll i=0;i<m;i++)
{
scanf("%lld%lld",&q[i].r,&q[i].l);
q[i].id=i;
}
sort(q,q+m,cmp);
ll ans=1;
ll l=0,r=1;
for(ll i=0;i<m;i++)
{
if(r<q[i].r)
{
for(;r<q[i].r;r++)
ans=(2*ans-C(r,l)+mod)%mod;
}
if(q[i].l<l)
{
for(;l>q[i].l;l--)
ans=(ans-C(r,l)+mod)%mod;
}
if(r>q[i].r)
{
for(r=r-1;r>=q[i].r;r--)
ans=(ans+C(r,l))*INV%mod;
r++;
}
if(q[i].l>l)
{
for(l=l+1;l<=q[i].l;l++)
ans=(ans+C(r,l))%mod;
l--;
}
ansa[q[i].id]=ans;
}
for(ll i=0;i<m;i++)
printf("%lld\n",ansa[i]);
}
6336 Problem E. Matrix from Arrays
题意
int cursor = 0;
for (int i = 0; ; ++i) {
for (int j = 0; j <= i; ++j) {
M[j][i - j] = A[cursor];
cursor = (cursor + 1) % L;
}
}
然后求M的子矩阵的和
题解
所以预处理左上角2L X 2L的矩阵的二维前缀和, O(1)回答询问。
代码
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;
ll M[1111][1111];
ll A[11];
int L;
ll get_num(ll x, ll y)
{
ll n = x + y;
n = (1 + n)*n / 2;
n = (n + x + 1) % L;
if (n == 0)
n += L;
return A[n - 1];
}
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
scanf("%d", &L);
for (int i = 0; i < L; i++)
scanf("%lld", &A[i]);
int cursor = 0;
for (int i = 0; i < 1000; ++i) {
for (int j = 0; j <= i; ++j) {
M[j][i - j] = A[cursor];
cursor = (cursor + 1) % L;
}
}
ll xun;
if (L % 2)xun = L;
else xun = 2 * L;
int q;
scanf("%d", &q);
while (q--)
{
ll sum = 0;
ll x1, x2, y1, y2;
scanf("%lld%lld%lld%lld", &x1, &y1, &x2, &y2);
ll zong = x2 - x1 + 1;
ll heng = y2 - y1 + 1;
ll zong1 = zong / xun;
ll heng1 = heng / xun;
ll yu_heng = heng % xun;
ll yu_zong = zong % xun;
ll fang = (zong / xun)*(heng / xun);
ll sum_fang = 0;
if (fang)
for (int i = 0; i < xun; i++)
for (int j = 0; j < xun; j++)
sum_fang += M[i][j];
sum_fang *= fang;
ll sum_zong = 0;
if (zong1)
for (int i = 0; i < xun; i++)
for (int j = 0; j < yu_heng; j++)
sum_zong += get_num(x1 + i, y1 + j);
sum_zong = zong1 * sum_zong;
ll sum_heng = 0;
if (heng1)
for (int i = 0; i < yu_zong; i++)
for (int j = 0; j < xun; j++)
sum_heng += get_num(x1 + i, y1 + j);
sum_heng = sum_heng * heng1;
ll sum_yu = 0;
for (int i = 0; i < yu_zong; i++)
for (int j = 0; j < yu_heng; j++)
sum_yu += get_num(i + x1, j + y1);
sum += sum_yu;
sum += sum_fang;
sum += sum_heng;
sum += sum_zong;
printf("%lld\n", sum);
}
}
}