集训日记:DAY9

集训日记:DAY9

集训还有1天啊!!!
今天考数论,我抱着视零如归的心态进入机房
因为我的数论水平仅停留在能看懂题解……


还是老规矩先遍历
T1……这什么玩意???看着像个好麻烦的递推???
T2像输油管道问题(雾,没啥思路……
T3这个我认识,是博弈论,好像是有向图游戏???我不会写呀……
T4一头雾水,除了暴力枚举系数没什么思路……
(此时过去10min)
又重新审视了一下4道题
想先推一下T1,如果到30min没退出来就放……
看了5min之后发现:
这好像是Catalan数???
然后手推了一下n=4的情况
发现答案是14!
这真是Catalan数!!!
兴奋得把板子呼上去……
仔细检查了开long long和取模的问题
确保“万无一失”(埋下伏笔)之后去写T4暴力
(此时过去1h)
T4我针对最高次小于2的情况进行系数暴力枚举
妄图水到30分
算了一下,如果3方枚举的话
枚举到125就会T……
反正也没什么思路,直接信仰就完了……
写完调完过去了30min
中途字典序的问题出现了亿点小问题,耽搁了时间
然后去看T2
至于T3这个“有向图游戏”……
弃掉吧……
T2硬是干想了1h仍然没有什么靠谱的思路……
于是就胡乱搞了个奇怪的贪心……
水过了样例,希望能得分……
(此时过去2.5h)
最后就剩T3
此时仍然认为不可做……
但是最后这1.5h也不能闲着呀
T3这个“有向图游戏”我是肯定写不出来的
硬写就是浪费时间
不如从样例找找规律面向数据编程
看了30min之后发现:
对于n=s=1的情况,直接输出1
对于s=1的情况,就是n/2向上取整
对于s=0分两种情况:
n为奇数时,答案为n/2向下取整
n为偶数时,直接输出0
别问我这么复制的规律我是怎么发现的……
问就是太闲了……

然后手推了一下好像还算靠谱
写完调完过去了3.5h
最后30min就是各种检查
确保“万无一失”……


中午吃饭的时候,突然想起T1Catalan数我没求逆元!!!
直接除的!!!
完几把犊子!!!
T1没了……
T2-T3还没有什么特别靠谱的做法
这下爆零了……


回去查分,看到没爆零松了口气……
75分,rank8
看小分T1居然过了10分!我爱zld!!!
T2乱搞贪心居然过了35分!我爱zld!!!
T3乱搞规律居然过了30分!我爱zld!!!
T4暴力枚举挂0了???
好吧其实也是意料之中
毕竟我就枚举到125……


下午订正的时候T1的码加了一行就A了……
挂掉90……加上这90就是rank2……


下面贴上正解和标程(今天我都订正了,所以贴的是我优美 的代码)

T1无题

集训日记:DAY9_第1张图片


为什么费小求逆元!!!线性不香吗???

#include
using namespace std;
const int N=200200,mod=1000000007;
int n,fac[N+N]={},rfac[N+N]={};
int rev(int x)
{
	int t=1,y=mod-2;
	while(y)
	{
		if(y&1) t=t*1ll*x%mod;
		x=x*1ll*x%mod;
		y>>=1;
	}
	return t;
}
int main()
{
//	freopen("notitle.in","r",stdin);
//	freopen("notitle.out","w",stdout);
	fac[0]=1;
	for(int i=1;i<N+N;++i)
		fac[i]=fac[i-1]*1ll*i%mod;
	rfac[N+N-1]=rev(fac[N+N-1]);
	for(int i=N+N-1;i>=1;--i)
		rfac[i-1]=rfac[i]*1ll*i%mod;
	int T,n;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d",&n);
		printf("%d\n",(int)(fac[n+n]*1ll*rfac[n]%mod*rfac[n+1]%mod));
	}
}

T2采油

很显然,一定存在一种最优解,使得其经过至少两个端点,因此可以直接在
2n 个端点中枚举直线,并判断每条直线穿过的线段的长度之和,这样做时间复
杂度是 O(n³)的,即可以得到 50 分。
为了优化,我们可以枚举基准点。对于枚举的每一个基准点,考虑过这个基
准点的直线的斜率倒数 1/k,在基准点看来,每条线段都对应着一个 1/k 的闭区
间,表示当 1/k 的值落在该范围内的时候,直线会与这条线段有公共点。
这样就把问题转化为选取一个点使得包含它的线段的权值之和尽可能大,这
是一个非常经典的问题,可以使用多种方式完成。
算法总时间复杂度 O(n²logn)。


范巨巨膜逆赛手切黑题!!!tql%%%ORZfxjer!!!

#include
#define ld long double
#define int long long 
using namespace std;
const int maxn=2005;
int n,x,y,h;
struct hwz
{
	int l,r,h;
}a[maxn];
struct qyt
{
	ld l,r;int w;	
}t[maxn];
struct lq
{
	ld x;int w;
	bool operator<(lq h)const{return x>h.x;}
};
ld dis(int u1,int v1,int u2,int v2)
{
	if(u1==u2) return u1;
	return (ld)(u2*v1-u1*v2)/(ld)(v1-v2);
}
bool cmp(qyt a,qyt b) {return a.l<b.l;}
signed main()
{
	cin>>n;
		int ans=0;
		for(int i=1;i<=n;i++)
		{
			cin>>a[i].l>>a[i].r>>a[i].h;
			if(a[i].l==a[i].r) i--,n--;
			if(a[i].l>a[i].r) swap(a[i].l,a[i].r);
		}
		for(int i=1;i<=n;i++)
		{
			int sum=0,tot=0;
			for(int j=1;j<=n;j++)
			{
				if(a[i].h==a[j].h) continue;
				ld l=dis(a[i].l,a[i].h,a[j].l,a[j].h);
				ld r=dis(a[i].l,a[i].h,a[j].r,a[j].h);
				if(l>r) swap(l,r);
				int w=a[j].r-a[j].l;
				t[++tot]=(qyt){l,r,w};
			}
			sort(t+1,t+1+tot,cmp);
			priority_queue<lq>q;
			sum=a[i].r-a[i].l;
			ans=max(ans,sum);
			for(int j=1;j<=tot;j++)
			{
				q.push((lq){t[j].r,t[j].w});
				sum+=t[j].w;
				while(!q.empty()&&q.top().x<t[j].l)
				{
					sum-=q.top().w;
					q.pop();
				}
				ans=max(ans,sum);
			}
		}
		cout<<ans<<endl;
	return 0;
}

T3分配

集训日记:DAY9_第2张图片
集训日记:DAY9_第3张图片


合着跟有向图游戏半毛钱关系没有……幸亏没硬写……
建议看一下CF原题面,不要翻译(手动滑稽

#include
using namespace std;
int main()
{
//	freopen("distribute.in","r",stdin);
//	freopen("distribute.out","w",stdout);
	int T;
	scanf("%d",&T);
	while(T--)
	{
		int n,S;
		scanf("%d%d",&n,&S);
		if(S==1) printf("%d\n",(n+1)/2);
		else
		{
			if(n%2) cout<<n/2<<endl;
			else
			{
				n/=2;
				int d=0;
				while((1<<d)<=n) ++d;
				--d;
				n-=(1<<d);
				cout<<n<<endl;
			}
		}
	}
	return 0;
}

T4多项式

集训日记:DAY9_第4张图片


呼呼呼ZZZ(已睡着)

#include
using namespace std;
long long a,b,c,ans=0,w[110]={};
int tot=0;
bool tryy(long long s1,long long s2)
{
	if(s1==0||s2==0)
	{
		if(s1==0&&s2==0)
		{
			ans++;
			return true;
		}
		else return false;
	}
	if(long long now=s2%b)
	{
		if((s1-now)%a==0)
		{
			w[++tot]=now;
			return tryy((s1-now)/a,(s2-now)/b);
		}
		else return false;
	}
	else
	{
		bool flag=false;
		int k=++tot;
		if(s1%a==0)
		{
			w[k]=0;
			flag=tryy(s1/a,s2/b);
		}
		if(s1==b&&s2==b)	
		{
			++ans;
			if(!flag)
			{
				w[k]=b;
				tot=k;
			}
			return true;
		}
		return flag;
	}
}
int main()
{	
	int T=1;
	cin>>T;
	while(T--)
	{
		cin>>a>>b>>c;
		tot=-1;
		ans=0;
		if(b==1)
		{
			puts(c==1?(a==1?"-1":"1\n0 1"):"0");
			continue;
		}
		tryy(b,c);
		cout<<ans<<endl;
		if(ans)
		{
			if(tot==-1)
			{
				tot=0;
				w[tot]=b;
			}
			cout<<tot<<" ";
			for(int i=tot;i>=0;--i) cout<<w[i]<<" ";
			cout<<endl;
		}
	}
	return 0;
}

你可能感兴趣的:(日记)