CSP&NOIP 2020游记


这大概是我唯一有用的一篇文章

CSP

T1

特殊情况卡掉一切格里高利;40pts

#include<iostream>
#include<cstdio>
using namespace std;
const int T=146097;//周期 
const int P=150000;//比周期略大一些的预处理范围 
const int baodi=2299160;//用这个来40分保底 
long long y,m,d,t,q,ans,kkk;//不用long long见90 
int num[15]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int NUM[15]={0,31,29,31,30,31,30,31,31,30,31,30,31};
bool ok(int a)
{
	if (a%400==0)return 1;
	if (a%4==0&&a%100!=0)return 1;
	return 0;
}
int sum(int a,bool ry)
{
	if(ry) return NUM[a];
	else return num[a];
}
void cal(int ru,int n){
	m=1;n+=1;
	if(ru==0) 
	{
		while(n>0)
		    n-=NUM[m++];
		if(n<=0)
		n+=NUM[--m];
		printf("%d %d ",n,m);
		return;
	}
	while(n>0)
		n-=num[m++];
	if(n<=0)
		n+=num[--m];
	printf("%d %d ",n,m);
	return;
}
int yy1[P],mm1[P],dd1[P];
void init()
{
	int MM,YY,DD;
	mm1[1]=MM=10,yy1[1]=YY=1582;dd1[1]=DD=15;
	for (int i=2;i<=T;i++)
	{
		DD++;
		if (DD>sum(MM,ok(YY)))DD=1,MM++;
		if (MM>12)MM=1,YY++;
		mm1[i]=MM,yy1[i]=YY,dd1[i]=DD;
	}
}
int main()
{
	//freopen("julian.in","r",stdin);
	//freopen("julian.out","w",stdout);
	scanf("%lld",&q);
	init();
	for(int i=1;i<=q;i++){
		y=-4712;
		scanf("%lld",&t);
		if(t<=baodi){
			ans=4*(t/1461);
			y+=ans;
			t-=(ans/4)*1461;
			while(t>365)
			{
				if(t>=731) {
					y++;t-=365;}
				if(t>=366&&t<731){
					t-=366;y++;break;}
			}
		}
		else{
			ans=t;
			ans-=baodi;
	        int Y=(ans/T)*400;ans%=T;
	        if(ans==0) ans=T,Y-=400;
	        m=mm1[ans],d=dd1[ans],y=Y+yy1[ans];
	        printf("%lld %lld %lld\n",d,m,y);
	        continue;
		}
		if(y<=1582&&y%4==0)		cal(0,t);
		else if(y<=1582&&y%4!=0) cal(1,t);
	    else if(y>1582&&(y%4==0&&y%100!=0||y%400==0)) cal(0,t);
	    else cal(1,t);
		if(y<=0) printf("%lld BC\n",-y+1);
		else printf("%lld\n",y);
	}
	return 0;
}


T2

完全没想出q没有用
然后我还不熟STL的数据结构!得到40pts

#include <cstdio>
#include <iostream>
#include <cstring>
#include <vector>
#define ll long long
#define ull unsigned long long
const int N=1e8+2;
using namespace std;
int n, m, c, k, cnt;
bool v[N];
ull a, p, q;
ull ans=1, res;
int main() {
	//freopen("zoo.in","r",stdin);
	//freopen("zoo.out","w",stdout);
	scanf("%d%d%d%d",&n,&m,&c,&k);
	cnt = k;
	if (!n && !m && k==64) {
		printf("18446744073709551616");
		return 0;
	}
	for (int i = 1; i <= n; i++) {
		scanf("%llu",&a);
		res |= a;
	}
	for (int i = 0; i < m; i++) {
		scanf("%d%d",&p,&q);
		if (!((res>>p)&1) && !v[p]) {
			cnt--;
			v[p] = 1;
		}
	}
	if(cnt) {
		ans=ans<<(cnt-1);
		ans*=2;
	}
	printf("%llu",ans-n);
	return 0;
}

右移求 2 ^ 64 2\quad\hat{}\quad64 2^64是1 具体可自行尝试


T3&T4

我连暴力都卡不出来

我的算法板子

NOIP前打的,完全没用;
想但没打字符串虽但迟到

数学
扩欧
#include<bits/stdc++.h>
using namespace std;
int a,b,c,d,x,y,t;
void exgcd(int a,int b,int &d,int &x,int &y){
    if(!b){x=1,y=0;return;}
    exgcd(b,a%b,d,y,x);
    y-=(a/b)*x;
}
int main()
{
	scanf("%d%d%d",&a,&b,&c);
	exgcd(a,b,d,x,y);
    if(c%d==0)
    { 
       x*=c/d; 
       t=b/d;
       t=abs(t);
       x=(x%t+t)%t;
       printf("%d\n",x); //通解 最小正整数 
       printf("%d\n",(c-a*x)/b);
    }
    return 0; 
}
图论
建边
void add(int u,int v) {
	E[tot].v = v;
	E[tot].next = head[u];
	head[u] = tot++;
}
遍历
void dfs(int u)
{
	int i;
	vist[u]=1;
    for(i=head[u];i;i=E[i].next)
    {
    	int to=E[i].v;
	    if(vist[to]==0)
	       dfs(to);
	}
}
堆优化
//第一关键字为dis,第二关键字为pos 
std::priority_queue<node> q;
inline void dijkstra()
{
    dis[s] = 0;
    q.push( ( node ){0, s} );
    while( !q.empty() )
    {
        node tmp = q.top();
        q.pop();
        int x = tmp.pos, d = tmp.dis;
        if( vis[x] )
            continue;
        vis[x] = 1;
        for( int i = head[x]; i; i = e[i].next )
        {
            int y = e[i].to;
            if( dis[y] > dis[x] + e[i].dis )
            {
                dis[y] = dis[x] + e[i].dis;
                if( !vis[y] )
                {
                    q.push( ( node ){dis[y], y} );
                }
            }
        }
    }
}
双连通分量
int dfs(int u,int fa) {
	low[u]=dfn[u]=++clock;
	s.push(u);
	for(int t=head[u]; t!=-1; t=E[t].next) {
		int v=E[t].v;
		if(!dfn[v]) {
			int lowv=dfs(v,u);
			low[u]=min(low[u],lowv);
			if(lowv>=dfn[u]) {
				bc++;
				bcc[bc].clear();
				int tmp=-1;
				while(!s.empty()) {
					tmp=s.top();
					s.pop();
					bcc[bc].push_back(tmp);
					if(tmp==v)break;
				}
				bcc[bc].push_back(u);
			}
		} else if(dfn[v]<dfn[u]&&fa!=v) {
			low[u]=min(low[u],dfn[v]);
		}
	}
	return low[u];
}
LCA
void Init() {
	int a,b;
	scanf("%d",&n);
	flag=0;
	for(int i=1; i<=n; i++) {
		head[i].clear();
		Que[i].clear();
		f[i]=i;
		r[i]=1;
		ancestor[i]=0;
		indegreen[i]=0;
		vis[i]=0;
	}
	for(int i=1;i<n;i++){
		scanf("%d%d",&a,&b);
		head[a].push_back(b);
		indegreen[b]++;
	}
	scanf("%d%d",&a,&b);
	Que[a].push_back(b);
	Que[b].push_back(a);
}
int Find(int u) {
	if(f[u]==u) return f[u];
	else f[u]=Find(f[u]);
	return f[u];
}
void Union(int v,int u) {
	int a,b;
	a=Find(v);
	b=Find(u);
	if(a==b) return;
	if(r[a]<=r[b]) {
		f[a]=b;
		r[b]+=r[a];
	} else {
		f[b]=a;
		r[a]+=r[b];
	}
}
void LCA(int k) {
	int size;
	size=head[k].size();
	for(int i=0; i<size; i++) {
		if(flag) break;
		LCA(head[k][i]);
		Union(k,head[k][i]);
		ancestor[Find(k)]=k;
	}
	vis[k]=1;
	size=Que[k].size();
	for(int i=0; i<size; i++)
		if(vis[Que[k][i]]) {
			flag=1;
			printf("%d\n",ancestor[Find(Que[k][i])]);
			return;
		}
}

NOIP

分数: 60 + 30 = 90 60+30=90 60+30=90
但是about T1

  • 补全了long long还是60
  • 改写了__int 128还是60
  • 听说能涨分,把lcm先除后乘,还是60

所以就不遗憾了叭(下面的码改过了,反正分都一样)

T1

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int M=1e5+5;
#define ll __int128
struct edge{
	int v,next;
}E[M*10];
ll gcd(ll a,ll b)
{
	if(b==0) return a;
	return gcd(b,a%b);
}
inline void print(__int128 x){
    if(x < 0){
        x = -x ;
        putchar('-');
    }
    if(x > 9){
        print(x/10);
    }
    putchar(x%10+'0');
}
ll a,b,cnt,A,B,zi,mu,n,m;
ll f1[M],f2[M],head[M],ind[M],outd[M];
void add(ll u,ll v)
{
	E[cnt].v=v;
	E[cnt].next=head[u];
	head[u]=cnt++;
}
void dfs(ll u)
{
	for(int i=head[u];i!=-1;i=E[i].next)
	{
		int to=E[i].v;
		if(f2[to]==0) {
			f1[to]=f1[u];
			f2[to]=f2[u]*outd[u];
		}
		else{
			A=f2[to],B=f2[u]*outd[u];
		    int lcm=A/gcd(A,B)*B; 
			mu=lcm;
			zi=mu*f1[u]/B+mu*f1[to]/f2[to];
			a=gcd(zi,mu);
			f1[to]=zi/a;f2[to]=mu/a;
		}
		dfs(to);
	}
	if(outd[u])  f1[u]=0,f2[u]=0;
	return;
}
int main()
{
    //freopen("water.in","r",stdin);
	//freopen("water.out","w",stdout);
	scanf("%lld%lld",&n,&m);
	memset(head,-1,sizeof(head));
	for(int i=1;i<=n;i++)
	{
		scanf("%lld",&outd[i]);
		for(int j=1;j<=outd[i];j++)
		{scanf("%lld",&b);
			add(i,b);
			ind[b]++;}
	}
	for(int i=1;i<=n;i++)
		if(ind[i]==0) add(0,i);
	f1[0]=m;f2[0]=1;outd[0]=m;
	dfs(0);
	for(int i=1;i<=n;i++)
		if(outd[i]==0){
			a=gcd(f1[i],f2[i]);
			f1[i]=f1[i]/a;f2[i]=f2[i]/a;
			print(f1[i]);
			printf(" ");
			print(f2[i]);
			printf("\n");
		}
	return 0;
}

注:这根本就不是topsort,其实它是可以的
(所以T1其实相当于没有算法吗)

T2&T3

我连暴力都卡不出来


T4

显然的暴力

但是为什么里面有一个-1啊

我这相当于亏了10分

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int M=1e5+5;
const int mod=1e9+7;
int n,k,step,flag;
int c[M],d[M];
int now[10],w[10],st[10];
bool judge()
{
	for(int i=1;i<=k;i++)
		    if(now[i]>w[i]||now[i]<1) return false;
	return  true;
}
bool judge2()
{
	for(int i=1;i<=k;i++)
		    if(now[i]!=st[i]) return false;
	return  true;
}
void cal()
{
	memcpy(now,st,sizeof(now));
	while(judge()){
		for(int i=1;i<=n;i++)
		{
			now[c[i]]+=d[i];
			step++;
		    if(!judge()) return;
		}
		if(judge2()) {flag=1;return;}
	}
}
void sth(int dep)
{
	if(dep==k+1) {cal();return;}
	for(int i=1;i<=w[dep];i++) {
		st[dep]=i;
	    sth(dep+1);
	}
	return;
}
int main()
{
	//freopen("walk.in","r",stdin);
	//freopen("walk.out","w",stdout);
	scanf("%d%d",&n,&k);
	for(int i=1;i<=k;i++)
	       scanf("%d",&w[i]);
	for(int i=1;i<=n;i++)
           scanf("%d%d",&c[i],&d[i]);
	sth(1);if(flag==1) step=-1;
	printf("%d",step);
	return 0;
}

没省一,大概率AFO~

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值