8月5日刷题日记

8月5日刷题日记

又划了一天

P3935 Calculating

数论分块板子题,考虑作为因数出现的次数。

\[Ans\ \ =\ \ \sum_{i=1}^{r} \lfloor \dfrac{r}{i} \rfloor \ \ - \ \ \sum_{j=1}^{l-1}\lfloor \dfrac{l-1}{j}\rfloor \]

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug cout<<"Szt ak ioi\n";
#define int long long

const int Mod=998244353;
const int N=1e6+7,M=2e3+1;

using namespace std;

inline int read() {
	int x=0,f=0;
	char ch=getchar();
	while(!isdigit(ch))f|=(ch=='-'),ch=getchar();
	while(isdigit(ch))x=(x<<1)+(x<<3)+(ch&15),ch=getchar();
	return f?-x:x;
}

int L,R;

int calc(int n){
	int l=1,r,res=0;
	while(l<=n){
		r=n/(n/l);
		res=(res+((r-l+1)*(n/l)%Mod))%Mod;
		l=r+1;
	}
	return res%Mod;
}

signed main() {
	L=read(),R=read();
	printf("%lld\n",((calc(R)-calc(L-1)+Mod)%Mod));
	return 0;
}

[USACO06DEC]Milk Patterns G

二分爆操后缀数组,二分长度,然后移动区间搞一搞就行了。

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug cout<<"Szt ak ioi\n";
#define int unsigned long long

const int Mod=1e9+7;
const int base=131;
const int N=1e6+7,M=2e3+1;

using namespace std;

inline int read() {
	int x=0,f=0;
	char ch=getchar();
	while(!isdigit(ch))f|=(ch=='-'),ch=getchar();
	while(isdigit(ch))x=(x<<1)+(x<<3)+(ch&15),ch=getchar();
	return f?-x:x;
}

int n,k,a[N];

int Pow(int a,int b){
	int res=1;
	while(b){if(b&1) res*=a;b>>=1;a*=a;}
	return res;
}

bool check(int mid){
	unordered_map<int,int>cnt;
	int calc=0;
	for(int i=1;i<=n;i++){
		if(i<=mid){
			calc=calc*base+a[i];
			cnt[calc]++;
			if(cnt[calc]>=k) return 1;
		}else{
			calc=calc*base+a[i];
			calc-=a[i-mid]*Pow(base,mid);
			cnt[calc]++;
			if(cnt[calc]>=k) return 1;
		}
	}return 0;
}

signed main() {
	n=read(),k=read();
	for(int i=1;i<=n;i++)a[i]=read();
	int l=1,r=n,Ans=0;
	while(l<=r){
		int mid=l+r>>1;
		if(check(mid)) l=mid+1,Ans=mid;
		else r=mid-1;
	}return 0&printf("%d\n",Ans);
}

P3400 仓鼠窝

处理出向上的高,再左右单调栈出能到达的位置,统计答案即可。

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define int long long
const int N=4e3+7;
using namespace std;

inline int read() {
	int x=0,f=0;
	char ch=getchar();
	while(!isdigit(ch))f|=(ch=='-'),ch=getchar();
	while(isdigit(ch))x=(x<<1)+(x<<3)+(ch^'0'),ch=getchar();
	return f?-x:x;
}

int n,m;
long long Ans;
bool vis[N][N];
int h[N][N],l[N],r[N],stc[N],sc;

signed main() {
	n=read();m=read();
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			char ch;
			cin>>ch;
			h[i][j]=(ch=='0')?0:h[i-1][j]+1;
		}
	}
	for(int i=1;i<=n;i++){
		sc=0;
		for(int j=1;j<=m;j++){
			while(sc&&h[i][stc[sc]]>=h[i][j]) sc--;
			l[j]=stc[sc];stc[++sc]=j;
		}
		sc=0;stc[++sc]=m+1;
		for(int j=m;j>=1;j--){
			while(sc&&h[i][stc[sc]]>h[i][j]) sc--;
			r[j]=stc[sc];stc[++sc]=j;
		}
		for(int j=1;j<=m;j++)Ans+=1LL*((j-l[j])*(r[j]-j)*h[i][j]);	
	}
	printf("%lld\n",Ans);
	return 0;
}

CF460C Present

算是差分吧,就是二分最小值然后差分 check 一下能不能达到最小值就行了。

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug cout<<"Szt ak ioi\n";
#define int long long

const int Mod=1e9+7;
const int N=1e6+7,M=2e3+1;

using namespace std;

inline int read() {
	int x=0,f=0;
	char ch=getchar();
	while(!isdigit(ch))f|=(ch=='-'),ch=getchar();
	while(isdigit(ch))x=(x<<1)+(x<<3)+(ch&15),ch=getchar();
	return f?-x:x;
}

int n,m,w,a[N],diff[N],D[N];

bool check(int mid){
	int res=0,ret=0;
	for(int i=1;i<=n;i++)D[i]=diff[i];
	for(int i=1;i<=n;i++){
		res+=D[i];
		if(res>=mid) continue;
		ret+=(mid-res);D[i]+=(mid-res);
		if(i+w<=n) D[i+w]-=(mid-res);
		res+=(mid-res);	
	}
	return ret<=m;
}

signed main() {
	int l=1e9,r=1e10,Ans=0;
	n=read(),m=read(),w=read();
	for(int i=1;i<=n;i++)a[i]=read(),diff[i]=a[i]-a[i-1],l=min(l,a[i]);
	while(l<=r){
		int mid=(l+r)>>1;
		if(check(mid)) l=mid+1,Ans=mid;
		else r=mid-1;
	}
	printf("%lld\n",Ans);
	return 0;
}
posted @ 2022-08-05 22:07  Gym_nastics  阅读(30)  评论(0编辑  收藏  举报