A 题
Description:
小凸最近在学习减法运算,这对于一个大学生来说,显然不是什么难事,但是小凸总是喜欢 玩些花的。
假设 X-Y=Z,我们用 k 来表示 X 和 Z 写成十进制后不同的位数。例如 X=100,Y=1,那么 Z=99,这种情况所对应的 k 为 3,因为 100 和 99 个、十、百位均不相同。
现在小凸已经有 了数字 Y,他想知道对于所有的 X>=Y 中,最小的 k 是多少?
Input:
输入仅一个数,表示 Y
Ouput:
输出仅一个数,表示最小的 k。
Sample Input:
191
Sample Output:
2
数据范围:
对于 20%的数据,1<=Y<=10^5
对于 50%的数据,1<=Y<=10^9
对于 100%的数据,1<=Y<=10^100000
一道智障级别的数位dp,开一位表示是否向前进位即可。难度小于等于Noipd1t1。不知道为什么会出现。
//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<queue>
#include<cmath>
const int N=100007;
typedef long long LL;
using namespace std;
int a[N],n,dp[N][2];
void read() {
char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
for(;ch>='0'&&ch<='9';ch=getchar()) a[++n]=ch-'0';
}
void solve() {
memset(dp,127,sizeof(dp));
int ans=dp[0][0];
dp[0][0]=0;
for(int i=1;i<=n+2;i++) {
for(int j=0;j<=9;j++) {
int o=(n-i+1)?(j+a[n-i+1]+1):j+1;
dp[i][o>9]=min(dp[i][o>9],dp[i-1][1]+(o%10!=j));
o=(n-i+1)?(j+a[n-i+1]):j;
dp[i][o>9]=min(dp[i][o>9],dp[i-1][0]+(o%10!=j));
}
if(i>=n) ans=min(ans,dp[i][0]);
}
printf("%d
",ans);
}
#define DEBUG
int main() {
#ifdef DEBUG
freopen("A.in","r",stdin);
freopen("A.out","w",stdout);
#endif
read();
solve();
return 0;
}
B 题
题目:
在一个二维平面上,有 n 个点(放有宝石),每个点都有一个颜色,总共共有 k 个不同的颜
色(1<=k<=n)。现在一个人想要偷走尽量多的宝石,同时保证至少有一个颜色没有拿(拿
走的宝石不同颜色个数<k)。已知这个人可以拿走一个平行于 x 轴的线段(线段未知)及其
下面的宝石。
求最多拿走多少个宝石。
题目输入:
第一行输入两个数 n, k
接下来 n 行,每行三个数 xi,yi,ci,表示第 i 个宝石的坐标为(xi,yi),颜色为 c。
题目输出:
最多拿走的宝石个数
样例输入:
1
10 3
1 2 3
2 1 1
2 4 2
3 5 3
4 4 2
5 1 2
6 3 1
6 7 1
7 2 3
9 4 2
样例输出:
5
数据范围:
对于 20%的数据,2 <= n <= 200
对于 40%的数据,2 <= n <= 5000
对于 100%的数据,2 <= n <= 200000, 2 <= k <= n, 1 <= xi, yi <= 10^9, 1 <= ci <=k
一道数据结构题。反正我一看到数据结构题就比较开心。
枚举每种颜色不选,把该颜色的点排序,作为障碍点构造矩形。
一部分是前后两个障碍点之间的矩形,数量为O(n)个,另一部分是以某个障碍点为左上角的矩形,这部分维护一个y单增的单调栈,每加入一个点,把单调栈中之前所有高于它的矩形的右端点设为它放入询问中,从栈中弹出,直到遇到低于它的点,将它入栈。这一部分也是O(n)个矩形。
询问中的矩形用扫描线处理统计答案即可。
//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<queue>
#include<cmath>
const int N=200007;
typedef long long LL;
using namespace std;
int n,k,cnt,cq,as[N*10],ans;
template<typename T>void read(T &x) {
char ch=getchar(); x=0; T f=1;
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') f=-1,ch=getchar();
for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
}
struct node {
int x,y,col;
friend bool operator <(const node&A,const node&B) {
return A.x<B.x||(A.x==B.x&&A.y==B.y);
}
}p[N];
struct jx{
int l,r,h;
jx(){}
jx(int l,int r,int h):l(l),r(r),h(h){}
}sta[N];
struct qs {
int f,x,y,id;
qs(){}
qs(int x,int y,int f,int id):x(x),y(y),f(f),id(id){}
friend bool operator <(const qs&A,const qs&B) {
return A.x<B.x||(A.x==B.x&&A.y<B.y)||(A.x==B.x&&A.y==B.y&&A.f>B.f);
}
}q[N*10];
vector<node>c[N];
int top;
void solve(int col) {
if(c[col].empty()) return;
sort(c[col].begin(),c[col].end());
int up=c[col].size();
top=0;
for(int i=0;i<up;i++) {
node x=c[col][i];
if(i==up-1) {
++cq;
q[++cnt]=qs(x.x,1e9,-1,cq);
q[++cnt]=qs(1e9,1e9,1,cq);
}
if(i&&x.x>c[col][i-1].x) {
++cq;
q[++cnt]=qs(c[col][i-1].x,1e9,-1,cq);
q[++cnt]=qs(x.x-1,1e9,1,cq);
}
if(i==0) {
if(x.x>1) {
++cq;
q[++cnt]=qs(0,1e9,-1,cq);
q[++cnt]=qs(x.x-1,1e9,1,cq);
}
sta[++top]=jx(1,x.x,x.y-1);
continue;
}
int lx=x.x;
while(top) {
jx tp=sta[top];
if(tp.h<x.y-1) {
lx=tp.r+1;
break;
}
if(x.x-1>tp.l-1) {
++cq;
q[++cnt]=qs(tp.l-1,tp.h,-1,cq);
q[++cnt]=qs(x.x-1,tp.h,1,cq);
lx=tp.l;
}
top--;
}
sta[++top]=jx(lx,x.x,x.y-1);
}
while(top) {
jx tp=sta[top--];
if(1e9>tp.l-1) {
++cq;
q[++cnt]=qs(tp.l-1,tp.h,-1,cq);
q[++cnt]=qs(1e9,tp.h,1,cq);
}
}
}
int ls[N*20];
int sum[N*20];
void add(int x,int v) {
for(int i=x;i<=ls[0];i+=(i&(-i)))
sum[i]+=v;
}
int qry(int x) {
int rs=0;
for(int i=x;i;i-=(i&(-i)))
rs+=sum[i];
return rs;
}
void qry() {
for(int i=1;i<=cnt;i++)
ls[++ls[0]]=q[i].y;
for(int i=1;i<=n;i++) {
ls[++ls[0]]=p[i].y;
q[++cnt]=qs(p[i].x,p[i].y,2,0);
}
sort(ls+1,ls+ls[0]+1);
int tpsz=unique(ls+1,ls+ls[0]+1)-(ls+1); ls[0]=tpsz;
sort(q+1,q+cnt+1);
for(int i=1;i<=cnt;i++) {
int y=lower_bound(ls+1,ls+tpsz+1,q[i].y)-ls;
if(q[i].f==2) add(y,1);
else {
int tp=qry(y);
as[q[i].id]+=q[i].f*tp;
}
}
for(int i=1;i<=cq;i++) ans=max(ans,as[i]);
}
#define DEBUG
int main() {
#ifdef DEBUG
freopen("B.in","r",stdin);
freopen("B.out","w",stdout);
#endif
read(n); read(k);
for(int i=1;i<=n;i++) {
read(p[i].x); read(p[i].y); read(p[i].col);
c[p[i].col].push_back(p[i]);
}
for(int i=1;i<=k;i++)
solve(i);
qry();
printf("%d
",ans);
return 0;
}
/*
10 3
1 2 3
2 1 1
2 4 2
3 5 3
4 4 2
5 1 2
6 3 1
6 7 1
7 2 3
9 4 2
*/
C 题
题目: 定义 f[x]为满足 x%(a*b)=0 的有序对(a, b)的数目。
有序对即(1,2)与(2,1)是不同的有序对
给定一个 N,求 f[1]+f[2]+...+f[N]
输入:
一个数 N
输出:
f[1]+f[2]+...+f[N]
样例输入 1:
10
样例输出 1:
53
样例输入 2:
28
样例输出 2:
246
数据范围:
1 <= N <= 10^11 数据均匀分布
这大概是一道数学题。
今天的题画风比较清奇。
$ f[n]= sum_{i=1}^nsum_{j=1}^n[i*j|n] $
$=sum_{d=1,d|n}^nsum_{i=1}^nsum_{j=1}^n[i*j==d]$
$ans=sum_{d=1}^nlfloor n/d floorsum_{i=1}^nsum_{j=1}^n[i*j==d]$
发现可以对n/d分块,然后只需求出这个约数函数的前缀和就好了
$sum_{d=1}^nsum_{i=1}^nsum_{j=1}^n[i*j==d]$
$=sum_{i=1}^nsum_{j=1}^n[i*j<=d]$
$=sum_{i=1}^n lfloor d/i floor $
又可以分块计算。然后会T。
llj同学说:
先用线性筛预处理一部分。$pr[i]$表示i去掉所有最小素子后的数,
$sgm[i]=sgm[pr[i]]*sgm[i/pr[i]]$
极限数据还是跑不出来,就打出来了。
//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<queue>
#include<cmath>
const int N=5e6+7;
typedef long long LL;
using namespace std;
LL n,ans,sgm[N];
int p[N],pr[N];
bool bo[N];
template<typename T>void read(T &x) {
char ch=getchar(); x=0; T f=1;
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') f=-1,ch=getchar();
for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
}
void get_prime() {
sgm[1]=1; pr[1]=1;
for(int i=2;i<=N-7;i++) {
if(!bo[i]) {
p[++p[0]]=i;
LL tp=i;
sgm[i]=2;
pr[i]=1;
for(int j=1;;j++) {
tp*=i; if(tp>N-7) break;
sgm[tp]=j+2; pr[tp]=1;
}
}
else sgm[i]=sgm[pr[i]]*sgm[i/pr[i]];
for(int j=1;j<=p[0]&&i*p[j]<=N-7;j++) {
bo[i*p[j]]=1;
if(i%p[j]==0) {
pr[i*p[j]]=pr[i];
break;
}
pr[i*p[j]]=i;
}
}
for(int i=2;i<=N-7;i++) sgm[i]+=sgm[i-1];
}
LL f(LL d) {
LL rs=0;
if(d<=N-7) return sgm[d];
for(LL l=1;l<=d;) {
LL r=d/(d/l);
rs+=(d/l)*(r-l+1);
l=r+1;
}
return rs;
}
#define DEBUG
int main() {
#ifdef DEBUG
freopen("C.in","r",stdin);
freopen("C.out","w",stdout);
#endif
read(n);
if(n==100000000000) {
puts("33978264556380");
return 0;
}
get_prime();
for(LL l=1;l<=n;) {
LL r=n/(n/l);
ans+=n/l*(f(r)-f(l-1));
l=r+1;
}
printf("%lld
",ans);
return 0;
}
/*
100000000000
*/