noip38
T1
有个朴素的暴力,枚举每一个子矩形,复杂度 \(O(n^{2}m^{2})\),观察数据范围,n很小,考虑枚举行,对于 \(m\) 用 \(two\;pointers\) 来维护。
先预处理出每一列的前缀和,然后枚举行,对于列,用个双指针,把 \([l,r]\) 这一段区间卡出来,答案每回累加合法的区间长度即可。
复杂度 \(O(n^{2}m)\)
Code
#include<cmath>
#include<cstdio>
#define MAX 50100
#define re register
#define int long long
namespace OMA
{
char ch[MAX];
int n,m,l,r,tot[MAX];
int ans,sum[33][MAX];
struct stream
{
template<typename type>inline stream &operator >>(type &s)
{
int w=1; s=0; char ch=getchar();
while(ch<'0'||ch>'9'){ if(ch=='-')w=-1; ch=getchar(); }
while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar(); }
return s*=w,*this;
}
}cin;
signed main()
{
//freopen("node.in","r",stdin);
cin >> n >> m;
for(re int i=1; i<=n; i++)
{
scanf("%s",ch+1);
for(re int j=1; j<=m; j++)
{ sum[i][j] = sum[i-1][j]+(ch[j]=='1'); }
}
cin >> l >> r;
for(re int i=1; i<=n; i++)
{
for(re int j=i; j<=n; j++)
{
int lp = 0,rp = 0;
for(re int k=1; k<=m; k++)
{
//printf("i=%lld j=%lld k=%lld ",i,j,k);
tot[k] = tot[k-1]+sum[j][k]-sum[i-1][k];
//printf("tot[%lld]=%lld\n",k,tot[k]);
while(tot[k]-tot[lp]>r&&lp+1<k)
{ lp++; }
while(tot[k]-tot[rp+1]>=l&&rp+1<k)
{ rp++; }
if(tot[k]-tot[rp]>=l)
{ ans += rp-lp+1; }
}
}
}
printf("%lld\n",ans);
return 0;
}
}
signed main()
{ return (OMA::main(),0); }
T2
题意转换

好了,现在你已经知道转换后的题意,问题在于如何求解 \(cnt\) 数组和答案。
对于每一行,我们都开一个桶记录 \(a\) 出现的次数。
然后枚举每一行,再从1枚举到最大值,再枚举当前枚举的数的倍数,加上上边说的桶即可 建议看code
这样得到的 \(cnt_{i,j}\) 表示第i行有多少个数为j的倍数,每一行求和就是总的,而我们要的是j,所以考虑一波容斥,即减去j的其他倍数即可,这样的话就要倒序枚举最大值。
复杂度 \(O(n(m+\max\{a\}\ln\max\{a\}))\) 。
Code
#include<cstdio>
#define MAX 100010
#define re register
#define int long long
const int N = 22;
namespace OMA
{
int n,m,xam,ans;
int a[N][MAX];
int buc[N][MAX];
int cnt[N][MAX],sum[MAX];
const int p = 1e9+7;
struct stream
{
template<typename type>inline stream &operator >> (type &s)
{
int w=1; s=0; char ch=getchar();
while(ch<'0'||ch>'9'){ if(ch=='-')w=-1; ch=getchar(); }
while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar(); }
return s*=w,*this;
}
}cin;
inline int max(int a,int b)
{ return a>b?a:b; }
signed main()
{
cin >> n >> m;
for(re int i=1; i<=n; i++)
{
for(re int j=1; j<=m; j++)
{ cin >> a[i][j]; xam = max(xam,a[i][j]); buc[i][a[i][j]]++; }
}
for(re int i=1; i<=n; i++)
{
for(re int j=1; j<=xam; j++)
{
for(re int k=1; j*k<=xam; k++)
{ cnt[i][j] += buc[i][j*k]; }
}
}
/*for(re int i=1; i<=n; i++)
{
for(re int j=1; j<=xam; j++)
{ printf("%lld ",cnt[i][j]); }
printf("\n");
}*/
for(re int j=xam; j; j--)
{
sum[j] = 1;
for(re int i=1; i<=n; i++)
{ (sum[j] *= cnt[i][j]+1) %= p; }
sum[j] -= 1;
if(!sum[j])
{ continue ; }
for(re int k=2; k*j<=xam; k++)
{ sum[j] -= sum[k*j]; }
(ans += j*sum[j]) %= p;
}
printf("%lld\n",(ans+p)%p);
return 0;
}
}
signed main()
{ return OMA::main(); }
T3
点分治,不会,爬了
noip38的更多相关文章
随机推荐
- 了解Javascript中函数作为对象的魅力
前言 Javascript赋予了函数非常多的特性,其中最重要的特性之一就是将函数作为第一型的对象.那就意味着在javascript中函数可以有属性,可以有方法, 可以享有所有对象所拥有的特性.并且最重 ...
- Java并发实战一:线程与线程安全
从零开始创建一家公司 Java并发编程是Java的基础之一,为了能在实践中学习并发编程,我们跟着创建一家公司的旅途,一起来学习Java并发编程. 进程与线程 由于我们的目标是学习并发编程,所以我不会把 ...
- python使用笔记24--面向对象编程2
类方法 类里面自带的方法,不用实例化就可以调用,想象,模型上自带的功能 类方法是公共的,在实例方法里面可以随意调用 但是在类方法里不能调用实例方法,不能使用实例变量,但是他可以调用其他的类方法 1 @ ...
- DNS域名解析四种配置实验 ---Linux DNS域名解析服务
DNS域名解析服务一.BIND域名服务基础1) DNS的定义2)域名结构3)DNS系统的作用① 正向解析:根据域名查找对应的IP地址② 反向解析:根据IP地址查找对应的域名③ DNS系统的分布式数据结 ...
- 用EXCEL打开CSV文件
1.打开EXCEL 2.数据--自文本--选择对应的CSV文件 3.设置表头所在的行(例如17行为表头)则输入17 4.确定分隔符 5.单击"确定"即可
- jieba分词处理
分词是一种数学上的应用,他可以直接根据词语之间的数学关系进行文字或者单词的抽象,比如,讲一句话"我来自地球上中国"进行单词分割,我们可能会得到如下的内容:"我" ...
- SpringBoot配置Https
HTTPS (全称:Hyper Text Transfer Protocol over SecureSocket Layer),是以安全为目标的 HTTP 通道,在HTTP的基础上通过传输加密和身份认 ...
- NDT匹配: The Normal Distributions Transform: A New Approach to Laser Scan
介绍 大多数激光匹配算法都是基于点或者线的特征匹配,该论文提出一种2D激光扫描匹配算法,方法类似于占据栅格,将2D平面分为一个个cell,对于每个cell,设定其一个正态分布,表示该网格测量到每个点的 ...
- Hive——基本DDL语句
Hive--基本DDL语句 DDL:Data Definition Language(数据定义语言,与关系型数据库相似) 官方手册:https://cwiki.apache.org/confluenc ...
- robotframework - PO设计
1.添加新建好的资源 2.测试用例原始代码如下(未做任何分离的数据) *** Settings ***Library SeleniumLibraryResource UI分层一.txtResource ...