總結——關於2017 10 8測試的分析總結

NOIP 2017 模拟



2017 10 8






T1 :


题目:





——正解思路:

将乘法问题转化为log相加问题,比较大小即可。

——我的乱搞:

变成除法问题,并剪枝,最后竟然Ac了。。。。



tips:

生命不息,数学不止。。。。



#include<cstdio>
int n,m,t,fa,fb,mini;
bool az,bz,fan;
float zj,a[100001],b[100001];
inline int read()
{
	int i=0;
	float f=1.0;
	char c=getchar();
	while((c<'0'||c>'9')&&c!='-') c=getchar();
	if(c=='-') f=-1.0,c=getchar();
	while(c>='0'&&c<='9') i=(i<<3)+(i<<1)+c-48,c=getchar();
	return i*f;
}
int main()
{
	t=read();
	while(t--)
	{
		n=read();
		fa=0,fb=0;
		az=false,bz=false,fan=false;
		for(int i=1;i<=n;++i)
		{
			a[i]=read();
			if(a[i]==0) az=true;
			if(a[i]<0) ++fa,a[i]=-a[i];
		}
		m=read();
		for(int i=1;i<=m;++i)
		{
			b[i]=read();
			if(b[i]==0) bz=true;
			if(b[i]<0) ++fb,b[i]=-b[i];
		}
		if((fa-fb)&1)
		{
			puts(fa&1 ? "Alice" : "Bob");
			continue;
		}
		else if((fa&1)&&(fb&1)) fan=true;
		if(az)
		{
			puts(!fan ? "Alice" : "Bob");
			continue;
		}
		if(bz)
		{
			puts(!fan ? "Bob" : "Alice");
			continue;
		}
		mini=n < m ? n : m;
		zj=1.0;
		for(int i=1;i<=mini;++i) zj*=a[i]/b[i];
		if(mini==n)
			for(int i=mini+1;i<=m;++i)
			{
				zj/=b[i];
				if(zj<1) break;
			}
		else
			for(int i=mini+1;i<=n;++i)
			{
				zj*=a[i];
				if(zj>1) break;
			}
		puts( !fan ? zj<1 ? "Alice" : "Bob" : zj>1 ? "Alice" : "Bob");
	}
	return 0;
}





T2 :



题目 :





——正解思路:


dp , 转移方程为 f [ i ][ j ] = min ( f [ i + 1 ][ j + 1 ] ,  f [ i + 1 ][ j ] ,  f [ i ][ j + 1 ] ) + a1 [ i + 1 ] * b2 [ j + 1 ];


——我的乱搞:

我选择狗带。。。



正解:

var
n, m, i, j : longint;
a, b : array [0..2002] of longint;
f : array [0..2002, 0..2002] of longint;
function min (a, b, c : longint) : longint;
begin
        if a < b then
                if a < c then exit (a)
                else if c < b then exit (c)
                else exit (b)
        else
                if b < c then exit (b)
                else if c < a then exit (c)
                else exit (a);
end;
begin
        read (n, m);
        for i := 1 to n do read (a[i]);
        for i := 1 to m do read (b[i]);
        fillchar (f, sizeof (f), 63);
        f[n + 1][m + 1] := 0;
        for i := n downto 1 do
                for j := m downto 1 do
                        f[i][j] := min (f[i + 1][j], f[i][j + 1], f[i + 1][j + 1]) + (a[i] - 1) * (b[j] - 1);
        write (f[1][1]);
end.




T3 : 


题目:




——正解思路:

用tarjan求双连通分量,然后答案减去每个双连通分量所可以产生的点的大小 C_size[ i ] ^ 2即可。

——我的乱搞:

双连通分量是什么鬼。。。。。惊恐



正解:

#include<stdio.h>
#include<time.h>
#include<algorithm>
using namespace std;
long long v[10001],ans;
int n,cnt;
inline long long read()
{
    long long i=0;
    char ch;
    for(ch=getchar();ch<'0'||ch>'9';ch=getchar());
    for(;ch>='0' && ch<='9';ch=getchar())
        i=(i<<3)+(i<<1)+ch-'0';
    return i;
}
inline long long gcd(long long a,long long b)
{
	return !b?a:gcd(b,a%b);
}
inline int find(int n,long long aim)
{
	if(v[n]==aim) return n;
	int l=0,r=n,mid=(l+r)>>1;
	for(;l+1<r;mid=(l+r)>>1)
		v[mid]<aim?l=mid:r=mid;
	return r;
}
int main()
{
	n=read();
	long long *a=new long long[n+1];
	long long *f=new long long[n+1];
	for(int i=1;i<=n;++i) a[i]=read();
	srand(time(0));
	random_shuffle(a+1,a+1+n);
	for(int i=1,p=min(n,4);i<=p;++i)
	{
		register int num=0;
		for(long long j=1;j*j<=a[i];++j)
			if(a[i]%j==0)
			{
				v[++num]=j;
				f[num]=0;
				if(j*j!=a[i])
				{
					v[++num]=a[i]/j;
					f[num]=0;
				}
			}
		sort(v+1,v+1+num);
		for(int j=1;j<=n;++j) ++f[find(num,gcd(a[i],a[j]))];
		for(int j=1;j<=num;++j)
		{
			register long long total=0;
			if(v[j]<=ans) continue;
			for(int k=j;k<=num;++k)
				if(v[k]%v[j]==0) total+=f[k];
			if(total*2>=n) ans=max(ans,v[j]);
		}
	}
	int num=0;
	char c[13];
    while(ans) c[++num]=(ans%10)+48,ans/=10;
    while(num) putchar(c[num--]);
    delete [] a;
    delete [] f;
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值