为了能到远方,脚下的每一步都不能少|

Aurora-JC

园龄:3年1个月粉丝:3关注:4

CSP-S 2020

日期计算以400年为周期,每400年都有恰好146097天。(146097=365×400+1004+1

预处理出400年内的情况,将年份模400即可快速得到答案。

几个简化代码的技巧:

对于格里高利历,以120011日为起始日,r 减去跳过的天数(2159351)。(2159351=1478×1461+310

(为什么要 +3 呢?因为从 1200 年后算法与儒略历不同,少算了闰年多的3天,再减去158210月少的 10 天,选择 1200 是因为刚好 400的倍数,且与 1582离得近)。

判断历法:r2299160即为儒略历 。

(2299160=1573×1461+731+31+28+31+30+31+30+31+31+30+3)

公元前xxx年视为 1x 年。

记得开 long long

#include<bits/stdc++.h>
#define N 146097 //格里高利历400年的天数
#define int long
using namespace std;
int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
int Q,n,year,month,day;
int d[N],m[N],y[N];
int md(int y,int m){ //格里高利历y年m月的天数
if(m==2) return y%4?28:(y%100?29:(y%400?28:29));
return (m==4||m==6||m==9||m==11)?30:31;
}
void pre(){
m[0]=d[0]=1;
for(int i=1;i<N;++i){
d[i]=d[i-1]+1,m[i]=m[i-1];y[i]=y[i-1];
if(d[i]>md(y[i],m[i])) ++m[i],d[i];
if(m[i]>12) m[i]=1,++y[i];
}
}//y[i],m[i],d[i]分别表示从011日经过i天的年月日
signed main(){
pre();
Q=read();
while(Q--){
n=read();
if(n>){ //格里高利历
}else{
year=n/1461*4-4712; //1461是儒略历4年的天数
n%=1461;
}
if(year+y[n]) printf("%d %d %lld\n",d[n],m[n],year+y[n]);
else printf("%d %d %lld BC\n",d[n],m[n],1-year-y[n]);
}
return 0;
}

P7076 [CSP-S2020] 动物园 :

考虑每一位,要么这一位被动物覆盖,要么这位不被动物覆盖,且这一位不需要饲料
。设符合的位的个数为 cnt,答案为 2cntn。这道题卡 unsigned long long 可以开 __int128,也可以特判过 cnt64 的情况。

if(k-cnt==64){
if(n) cout<<ull(-n)<<endl;
else cout<<"18446744073709551616"<<endl;
}

当然你不需要背下 18446744073709551616 来,只要先输出一个(unsigned long long)-1 再加上 1 就行了。

O(kn)

#include<bits/stdc++.h>
#define N 1000005
#define int __int128
using namespace std;
int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
int n,m,c,k,cnt;
int a[N],p[N],q[N];
int b[N],flag[N];
void write(int x){
if(x>9) write(x/10);
putchar(x%10+'0');
}
signed main(){
n=read(),m=read(),c=read(),cnt=k=read();
for(int i=1;i<=n;++i) a[i]=read();
for(int i=1;i<=m;++i) p[i]=read(),q[i]=read(),b[p[i]]++;
for(int i=1;i<=n;++i){
int x=a[i];
int pos=0;
while(x){
if(x&1) flag[pos]=1;
x>>=1,pos++;
}
}
for(int i=0;i<=k;++i) if(!flag[i]&&b[i]) cnt--;
int ans=1;
for(int i=1;i<=cnt;++i) ans*=2;
write(ans-n);
return 0;
}

O(n)

先开一个数组 bucj 表示是否有 ai 的第 j 位上是 1

又看到题目中保证 qi 互不相同,所以一旦出现 pi,qi 满足 bucpi=0,那么这一位就不能选,因为当前买的饲料中必定没有 qi

不妨设剩下来 bit 位,那么这 bit 位既可以是 0 也可以是 1,共有 2bit 种动物,减去现有的 n 种动物即可。

注意要特判 bit=64,n=0 的情况。读入量较大,建议写快读。

此外 buc 数组可以用 unsigned long long 变量代替,这样就做到了时间 O(n+m),空间 O(1)

非自己代码:

#include <bits/stdc++.h>
using namespace std;
#define ull unsigned long long
#define gc getchar()
inline ull rd(){
ull x=0; char s=gc;
while(!isdigit(s))s=gc;
while(isdigit(s))x=(x<<1)+(x<<3)+s-'0',s=gc;
return x;
} ull n,m,c,k,ans,lim,hv;
int main(){
n=rd(),m=rd(),c=rd(),k=rd();
for(int i=1;i<=n;i++)hv|=rd(); // 统计每个位是否有 1
for(int i=1;i<=m;i++)lim|=1ull<<rd(),rd(); // 统计有限制的位
for(int i=0;i<k;i++)ans+=!((lim>>i)&1)||((hv>>i)&1); // 如果当前位有 1, 或者没有限制,那么都可以选
if(ans==64&&!n)puts("18446744073709551616");
else cout<<(ans==64?-n:(1ull<<ans)-n)<<endl;
return 0;
}

P7077 [CSP-S2020] 函数调用 :

P7078 [CSP-S2020] 贪吃蛇 :

本文作者:Aurora-JC

本文链接:https://www.cnblogs.com/jiangchen4122/p/17464586.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Aurora-JC  阅读(70)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起