加载中…

返回上一页

CSP 考前欢乐赛

下发文件(密码为原 accoders 比赛密码)

炒币

发现数列中数肯定是上下波动的,一定是要去选每一段最大的和最小的.

点击查看代码
#include<bits/stdc++.h>
#define ll long long
#define rg register
#define rll rg ll
#define maxn 200001
#define put_ putchar(' ')
#define putn putchar('\n')
using namespace std;
inline ll read()
{
	rg bool f=0;rll x=0;rg char ch=getchar(); while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
	while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^'0'),ch=getchar(); return f?-x:x;
}
inline void write(rll x) { if(x<0) putchar('-'),x=-x; if(x>9) write(x/10); putchar(x%10|'0'); }
ll n,mx,mn,id1,id2;
ll a[maxn];
bool ans[maxn];
int main()
{
	freopen("coin.in","r",stdin); freopen("coin.out","w",stdout);
	n=read(); for(rll i=1;i<=n;i++) a[i]=read();
	for(rll i=1;i+1<=n;)
	{
		mx=0,mn=0x3f3f3f3f3f3f3f3f;
		while(i+1<=n&&a[i+1]>=a[i]) i++;
		while(i+1<=n&&a[i+1]<=a[i])
		{
			if(mx<a[i]) mx=a[i],id1=i; if(mn>a[i]) mn=a[i],id2=i; i++; if(mx<a[i]) mx=a[i],id1=i; if(mn>a[i]) mn=a[i],id2=i;
		}
		if(mx) ans[id1]=ans[id2]=1;
	}
	for(rll i=1;i<=n;i++) write(ans[i]),put_;
	return 0;
}

凑数

一个贪心的想法是先尽量选价值高的那个数,然后再选价值低的数. 但是可能会有更优的情况. 因此可以枚举那个价值最大的放几个,然后尽可能用后面的那个填(前提是价值比 1 的高),最后拿 1 补全.

然后妥妥得 TLE. 居然还有 80 分,假贪心 1 分都没有的 发现前面的 lcm(y , z) 部分对后面的选择是没有影响的,所以直接加一下. 复杂度是根号的,证明就不说了.

点击查看代码
#include<bits/stdc++.h>
#define ll long long
#define rg register
#define rll rg ll
#define maxn 200001
#define put_ putchar(' ')
#define putn putchar('\n')
using namespace std;
inline ll read()
{
	rg bool f=0;rll x=0;rg char ch=getchar(); while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
	while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^'0'),ch=getchar(); return f?-x:x;
}
inline void write(rll x) { if(x<0) putchar('-'),x=-x; if(x>9) write(x/10); putchar(x%10|'0'); }
ll t,n,a,b,c,x,y,z,ans,pp;
int main()
{
	freopen("cs.in","r",stdin); freopen("cs.out","w",stdout);
	t=read();while(t--)
	{
		n=read();a=1;b=read();c=read();x=read();y=read();z=read();
		y=min(y,b*x);z=min(z,c*x);
		if(b>c) swap(y,z),swap(b,c);
		rll t=max(n/(b*c)-1,0ll);n-=t*b*c;
		pp=min(y*c,z*b)*t;ans=0x7fffffffffffffff;
		for(rll p=0,n1,an;p<=n/b;p++)
		{
			n1=n;
			an=p*y;n1-=p*b; an+=(n1/c)*z;n1%=c;an+=(n1*x);ans=min(an,ans);
			// cout<<an<<' ';
		}
		write(ans+pp);putn;
	}
	return 0;
}

同构

容易发现含有平方因子的数一定是可以和不含有平方因子的数组合到一起.

那么进行一遍筛,筛出这些组合即可.

这样不全. 发现某些素数的 n 倍是可以组合的. 比如 n = 14 时,5,107,14 可以互换. 找一下这个然后乘一下组合数即可.

点击查看代码
#include<bits/stdc++.h>
#define ll long long
#define rg register
#define rll rg ll
#define maxn 2000001
#define mod 1000000007
#define put_ putchar(' ')
#define putn putchar('\n')
using namespace std;
inline ll read()
{
	rg bool f=0;rll x=0;rg char ch=getchar(); while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
	while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^'0'),ch=getchar(); return f?-x:x;
}
inline void write(rll x) { if(x<0) putchar('-'),x=-x; if(x>9) write(x/10); putchar(x%10|'0'); }
ll n,ans=1;
ll p[maxn],cnt,jc[maxn],s[maxn];
ll bel[maxn],tot=1,sum[maxn];
bool fl[maxn],flag[maxn];
inline ll ksm(rll a,rll b) { rll ans=1; a%=mod; for(rll i=b;i;i>>=1) { if(i&1) (ans*=a)%=mod; (a*=a)%=mod; } return ans; }
inline void shai()
{
	fl[1]=bel[1]=1; for(rll i=2;i<=n;i++)
	{
		if(!fl[i]) p[++cnt]=i,bel[i]=++tot;// ,write(i),putn;
		for(rll j=1;j<=cnt&&i*p[j]<=n;j++) { fl[i*p[j]]=1; if(flag[i*p[j]]) continue; if(!(i%p[j])) { bel[i*p[j]]=bel[i]; flag[i*p[j]]=1; } else bel[i*p[j]]=++tot; }
	}
	for(rll i=1;i<=n;i++) { if((!fl[i])&&(i<<1)>n) bel[i]=1; sum[bel[i]]++; }
	for(rll i=1;i<=cnt;i++) s[n/p[i]]++;
	// for(rll i=1;i<=n;i++) { for(rll j=1;j<=n;j++) if(bel[j]==i) write(j),put_;putn; }
}
int main()
{
	// 1,2,3,4,5 ,6,7 ,8 ,9 ,10,11,12
	// 1,2,6,4,12,4,12,36,72,24,72,144
	freopen("tg.in","r",stdin); freopen("tg.out","w",stdout);
	jc[0]=1; for(rll i=1;i<maxn;i++) jc[i]=jc[i-1]*i%mod;
	// ny[maxn-1]=ksm(maxn-1,mod-2); for(rll i=maxn-2;i;i--) ny[i]=ny[i+1]*(i+1)%mod;
	// for(rll n=1;n<=12;n++)
	// {
	// 	n=55;
	// 	for(rll i=1;i<=n;i++) p[i]=i;ans=0;
	// 	for(rll p0=1;p0<=n;p0++) for(rll q=p0+1;q<=n;q++)
	// 	{
	// 		fl[0]=0;swap(p[p0],p[q]);
	// 		for(rll i=1;i<=n;i++) for(rll j=i+1;j<=n;j++) if(gcd(i,j)==1&&gcd(p[i],p[j])!=1) { fl[0]=1; break; }
	// 		if(!fl[0]) { ans++;write(p0);put_;write(q);putn; }swap(p[p0],p[q]);
	// 	} //while(next_permutation(p+1,p+n+1));
	// 	return 0;
	// }
	// 55的过不去,少了2倍??小数据都没有问题 out=98202841 ans=196405682
	// db 没问题啊……
	// 处于相同的belong中
	// 1 29 31 37 41 43 47 53
	// 2 4 8 16 32
	// 3 9 27
	// 6 12 18 24 36 48 54
	// 5 25
	// 10 20 40 50
	// 15 45
	// 7 49
	// 14 28
	// 21
	// 35
	// 11
	// 22 44
	// 33
	// 55
	// 13
	// 26 52
	// 39
	// 30
	// 17
	// 34
	// 51
	// 19
	// 38
	// 42
	// 23
	// 46
	// 可以交换的
	// 1 29
	// 1 31
	// 1 37
	// 1 41
	// 1 43
	// 1 47
	// 1 53
	// 2 4
	// 2 8
	// 2 16
	// 2 32
	// 3 9
	// 3 27
	// 4 8
	// 4 16
	// 4 32
	// 5 25
	// 6 12
	// 6 18
	// 6 24
	// 6 36
	// 6 48
	// 6 54
	// 7 49
	// 8 16
	// 8 32
	// 9 27
	// 10 20
	// 10 40
	// 10 50
	// 12 18
	// 12 24
	// 12 36
	// 12 48
	// 12 54
	// 14 28
	// 15 45
	// 16 32
	// 18 24
	// 18 36
	// 18 48
	// 18 54
	// 20 40
	// 20 50
	// 22 44
	// 24 36
	// 24 48
	// 24 54
	// 26 52
	// 29 31
	// 29 37
	// 29 41
	// 29 43
	// 29 47
	// 29 53
	// 31 37
	// 31 41
	// 31 43
	// 31 47
	// 31 53
	// 36 48
	// 36 54
	// 37 41
	// 37 43
	// 37 47
	// 37 53
	// 40 50
	// 41 43
	// 41 47
	// 41 53
	// 43 47
	// 43 53
	// 47 53
	// 48 54
	// 据理手算应该就是98202841啊...也不知道哪里少了2倍
	// upd:原来17和19能换啊,那就切了,差点场切黑题啊啊啊,,,
	n=read();shai(); for(rll i=1;i<=tot;i++) if(sum[i]) (ans*=jc[sum[i]])%=mod;
	for(rll i=2;i<=n;i++) if(s[i]>1) (ans*=jc[s[i]])%=mod; write(ans);
	return 0;
}

重建

显然这里讲得比我好.

点击查看代码
#include<bits/stdc++.h>
#define ll long long
#define rg register
#define rll rg ll
#define pll pair<ll,ll>
#define maxn 200001
#define put_ putchar(' ')
#define putn putchar('\n')
using namespace std;
inline ll read()
{
	rg bool f=0;rll x=0;rg char ch=getchar(); while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
	while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^'0'),ch=getchar(); return f?-x:x;
}
inline void write(rll x) { if(x<0) putchar('-'),x=-x; if(x>9) write(x/10); putchar(x%10|'0'); }
struct node
{
	ll x,to,v;
	inline friend bool operator<(rg node a,rg node b) { return a.v<b.v; }
}e[maxn];
ll n,m,l,r,a[maxn],b[maxn],f[maxn],d[maxn],id[maxn],ans;
vector<ll> st;
bool s[maxn];
inline bool cmp(rll x,rll y) { return a[x]<a[y]; }
inline ll find(rll x) { if(x^f[x]) f[x]=find(f[x]); return f[x]; }
int main()
{
	freopen("rb.in","r",stdin); freopen("rb.out","w",stdout);
	n=read();m=read(); for(rll i=1,u,v,d;i<=m;i++) e[i]={ read()+1,read()+1,read() };
	l=read(); for(rll i=1;i<=l;i++) a[i]=read(),b[i]=read(); r=read(); for(rll i=1;i<=r;i++) s[read()+1]=1;
	sort(e+1,e+m+1); for(rll i=1;i<=n;i++) f[i]=i;
	for(rll i=1,x,y;i<=m;i++)
	{
		x=find(e[i].x),y=find(e[i].to);if(x==y) continue;ans+=e[i].v;
		if(s[x]&&s[y]) st.push_back(e[i].v); f[x]=y; s[y]|=s[x];
	}
	ans*=l; for(rll i=1;i<=l;i++) ans+=b[i]*(n-1);
	for(rll i=st.size()-1;~i;i--) d[i+1]=d[i+2]+st[i];
	for(rll i=1;i<=l;i++) id[i]=f[i]=i; sort(id+1,id+l+1,cmp);
	for(rll i=1,x,y,pos;i<l;i++)
	{
		x=find(id[i]);y=find(id[i]%l+1); if(b[x]<b[y]) swap(x,y); f[x]=y;
		pos=lower_bound(st.begin(),st.end(),a[id[i]]-b[x])-st.begin();
		ans+=(st.size()-pos+1)*a[id[i]]-(st.size()-pos)*b[x]-d[pos+1];
	}
	write(ans);
	return 0;
}

祝大家 CSP-S Rp++!

posted @ 2022-10-28 19:01  1Liu  阅读(27)  评论(0编辑  收藏  举报