[考试总结]noip模拟69(多校)

石子游戏

这个的部分分数 \(50pts\) 需要使用 \(SG\) 函数。。

因为上次颓废,然后就没有学。。。

一个堆的 \(SG\) 函数就是最高的那个 \(SG\)

然后我们的 \(SG\) 函数就是递推而成。

我们将这个东西所能到达的所有状态的 \(SG\) 值排序,之后我们就可以找到第一个没出现的非负整数,这个就是他的 \(SG\) 值。

然后这样的话是 \(\mathcal O(n^3)\) 的,只有 \(20pts\)

有一个规律,就是一个堆的 \(SG\) 值就是这个 \(a_i \% (k+1)\),之后就可以 \(50pts\) 了。



#include<bits/stdc++.h>
using namespace std;
#define try(i,a,b) for(register int i=a;i<=b;++i)
#define throw(i,a,b) for(register int i=a;i>=b;--i)
#define go(i,x) for(register signed i=head[x],y=edge[i].ver;i;i=edge[i].next,y=edge[i].ver)
namespace xin_io
{
	#define file(x) FILE *FI = freopen(#x".in","r",stdin); FI = freopen(#x".out","w",stdout);
	#define sb(x) cout<<#x" = "<<x<<' '
	#define jb(x) cout<<#x" = "<<x<<endl
	#define debug cout<<"debug"<<endl
	#define gec() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1 ++
	#define gc() getchar()
	#define scanf ak = scanf
	char buf[1<<20],*p1 = buf,*p2 = buf; using ll = long long; using ull = unsigned long long; int ak;
	class xin_stream{public:template<typename type>xin_stream &operator >> (type &s)
	{
		s = 0; register bool f = 0; register char ch = gc();
		while(!isdigit(ch)) f |= ch == '-',ch = gc();
		while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch xor 48),ch = gc(); return s = f ? -s : s,*this;
	}}io;
}
using namespace xin_io; static const int maxn = 1e6+10,two = 4e3+10,inf = 1e9+10;
#define int long long
namespace xin
{
	int sg[maxn];
	int n,a[maxn],maxx;
	int temp[maxn],zhi = 0;
	bool vis[maxn];
	inline short main()
	{
		file(stone);
		io >> n;
		try(i,1,n) io >> a[i],maxx = max(maxx,a[i]);
		auto check = [](int k) -> bool
		{
//			try(i,1,maxx)
//			{
//				zhi = 0;
//				throw(j,i-1,i-k)
//					if(j < 0) break;
//					else temp[++zhi] = sg[j],vis[sg[j]] = 1;
////				std::sort(temp+1,temp+zhi+1);
//				for(register int j=0;;j++) if(!vis[j]) {sg[i] = j; break;}
//				try(j,1,zhi) vis[temp[j]] = 0;
//			}
			int ret = 0;
			try(i,1,n) ret ^= (a[i] % (k + 1));
//			jb(k);
//			try(i,1,maxx) jb(sg[i]);
			return ret;
		};
		try(i,1,n)
			printf(check(i) ? "Alice " : "Bob ");
		return 0;
	}
}
signed main() {return xin::main();}

黑客1

这个就是垃圾题。

枚举就行了。

然后将两个倍数的区间进行判断就行,其实就是找到交集。。。



#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register int i=a;i<=b;++i)
#define throw(i,a,b) for(register int i=a;i>=b;--i)
#define go(i,x) for(register signed i=head[x],y=edge[i].ver;i;i=edge[i].next,y=edge[i].ver)
namespace xin_io
{
	#define file(x) FILE *FI = freopen(#x".in","r",stdin); FI = freopen(#x".out","w",stdout);
	#define sb(x) cout<<#x" = "<<x<<' '
	#define jb(x) cout<<#x" = "<<x<<endl
	#define debug cout<<"debug"<<endl
	#define gec() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1 ++
	#define gc() getchar()
	#define scanf ak = scanf
	char buf[1<<20],*p1 = buf,*p2 = buf; using ll = long long; using ull = unsigned long long; int ak;
	class xin_stream{public:template<typename type>xin_stream &operator >> (type &s)
	{
		s = 0; register bool f = 0; register char ch = gc();
		while(!isdigit(ch)) f |= ch == '-',ch = gc();
		while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch xor 48),ch = gc(); return s = f ? -s : s,*this;
	}}io;
}
using namespace xin_io; static const int maxn = 1e6+10,two = 4e3+10,inf = 1e9+10;
#define int long long
namespace xin
{
	const int mod = 1e9+7;
	int a,b,c,d,jsq,ans;
	inline int gcd(int x,int y) {return !y ? x : gcd(y,x%y);}
	inline short main()
	{
		freopen("hacker.in","r",stdin); freopen("hacker.out","w",stdout);
		io >> a >> b >> c >> d;
		if(b <= 1000 and d <= 1000)
		{
			auto check = [](int x,int y)
			{
				register int yue = gcd(x,y);
				if(yue) x /= yue,y /= yue;
				if(x + y <= 999) return x+y;
				return 0ll;
			};
			try(i,a,b) try(j,c,d)
				jsq += check(i,j),jsq -= (jsq >= mod) ? mod : 0;
			cout<<jsq % mod<<endl;
			return 0;
		}
		int ms1 = std::min(999ll,b),ms2 = std::min(999ll,d);
		try(i,1,ms1) try(j,1,ms2-i)
		if(gcd(i,j) == 1)
		{
			int l1,r1,l2,r2;
			l1 = (a + i - 1) / i; r1 = b / i;
			l2 = (c + j - 1) / j; r2 = d / j;
			if(r1 >= l2 and l1 <= l2 and r2 >= r1)
				ans += (r1 - l2 + 1) * (i + j) % mod,ans %= mod;
			else if(r2 >= l1 and l2 <= l1 and r1 >= r2)
				ans += (r2 - l1 + 1) * (i + j) % mod,ans %= mod;
			else if(r2 >= r1 and l2 <= l1) ans += (r1 - l1 + 1) * (i + j) % mod,ans %= mod;
			else if(r1 >= r2 and l2 >= l1) ans += (r2 - l2 + 1) * (i + j) % mod,ans %= mod;
		}
		cout<<ans<<endl;
		return 0;
	}
}
signed main() {return xin::main();}

黑客2

垃圾高精,超级卡常,然后使用 \(nb\) 方法可以过掉。。



#include<bits/stdc++.h>
using namespace std;
#define try(i,a,b) for(register int i=a;i<=b;++i)
#define throw(i,a,b) for(register int i=a;i>=b;--i)
#define go(i,x) for(register signed i=head[x],y=edge[i].ver;i;i=edge[i].next,y=edge[i].ver)
namespace xin_io
{
	#define file(x) FILE *FI = freopen(#x".in","r",stdin); FI = freopen(#x".out","w",stdout);
	#define sb(x) cout<<#x" = "<<x<<' '
	#define jb(x) cout<<#x" = "<<x<<endl
	#define debug cout<<"debug"<<endl
	#define gec() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1 ++
	#define gc() getchar()
	#define scanf ak = scanf
	char buf[1<<20],*p1 = buf,*p2 = buf; using ll = long long; using ull = unsigned long long; int ak;
	class xin_stream{public:template<typename type>xin_stream &operator >> (type &s)
	{
		s = 0; register bool f = 0; register char ch = gc();
		while(!isdigit(ch)) f |= ch == '-',ch = gc();
		while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch xor 48),ch = gc(); return s = f ? -s : s,*this;
	}}io;
}
using namespace xin_io; static const int maxn = 1e6+10,two = 4e3+10,inf = 1e9+10;
int n,m,k;
#define int long long
namespace xin
{
	const ll bse = 1e9;
	struct bigint
	{
		ll a[250];int len;
		bigint(){len = 1;}
		bigint(int x){
			memset(a,0,sizeof(a));len = 1;
			while(x){a[len++] = x % bse,x /= bse;}len --;
		}
		void print(){
			printf("%lld",a[len]);
			for(register int i = len-1 ; i ; i --)printf("%09lld",a[i]);
		}
		void pprint()
		{
			printf("%lld",a[len]);
			throw(i,len-1,1) printf("%017lld",a[i]);
//			printf("%016lld",a[1]);
		}
		friend bigint operator + (const bigint& a,const bigint& b){
			bigint ret = 0; ret.len = max(a.len,b.len) + 1;
			for(register int i = 1 ; i <= ret.len ; i ++)
				ret.a[i] += a.a[i] + b.a[i],
				ret.a[i+1] += ret.a[i] / bse,
				ret.a[i] %= bse;
			for(register int i = 1 ; i <= ret.len ; i ++)
				ret.a[i+1] += ret.a[i] / bse,
				ret.a[i] %= bse;
			while(ret.len > 1 && !ret.a[ret.len]) ret.len --;
			return ret;
		}
		friend bigint operator * (const bigint& a,const bigint& b){
			bigint ret = 0; ret.len = a.len + b.len + 1;
			for(register int i = 1 ; i <= a.len ; i ++)
				for(int j = 1 ; j <= b.len ; j ++)
					ret.a[i+j-1] += a.a[i] * b.a[j],
					ret.a[i+j] += ret.a[i+j-1] / bse,
					ret.a[i+j-1] %= bse;
			for(register int i = 1 ; i <= ret.len ; i ++)
				ret.a[i+1] += ret.a[i] / bse ,
				ret.a[i] %= bse;
			while(ret.len > 1 && !ret.a[ret.len]) ret.len --;
			return ret;
		}
		friend bigint operator * (const bigint& a,const int &b){
			bigint ret = 0 ; ret.len = a.len;
			int x = b;
			while(x) ret.len ++ , x /= bse;
			for(register int i = 1 ; i <= a.len ; i ++)
				ret.a[i] += a.a[i] * b,
				ret.a[i+1] += ret.a[i] / bse,
				ret.a[i] %= bse;
			for(register int i = 1 ; i <= ret.len ; i ++)
				ret.a[i+1] += ret.a[i] / bse,
				ret.a[i] %= bse;
			while(ret.len > 1 && !ret.a[ret.len]) ret.len --;
			return ret;
		}
	};
	bigint ans1 = 0,ans2 = 0,ans = 0,pow2 = 1;
	bool vis[two][two];
	int st[maxn];
	bigint f[130001];
	class xin_data
	{
		public:
			int x,y;
			xin_data(){}
			xin_data(int x,int y):x(x),y(y){}
	}d[two/5][two/5];
	int tot;
	bigint shi[501];
	xin_data dfs(int x,int s)
	{
		if(vis[x][s]) return d[x][s];
		vis[x][s] = 1; 
		if(x == n + 1) return d[x][s] = xin_data(1,0);
		register int temp1 = ++tot,temp2 = ++tot;
		try(i,1,k) if(!(s & (1 << i - 1)))
		{
			xin_data temp = dfs(x+1,s|st[i]);
			f[temp1] = f[temp1] + f[temp.x];
			f[temp2] = f[temp2] + f[temp.y];
			bigint wk = f[temp.x] * i * shi[n-x];
			f[temp2] = f[temp2] + wk;
		}
		return d[x][s] = xin_data(temp1,temp2);
	}
	inline short main()
	{
		try(i,1,m)
		{
			register int x,y; io >> x >> y;
			st[x] |= (1 << y - 1);
		}
		shi[0] = 1;
		try(i,1,500) shi[i] = shi[i-1] * 10;
		f[1] = 1; tot = 1;
		xin_data ans = dfs(1,0);
		f[ans.x].print(); cout<<endl;
		f[ans.y].print(); cout<<endl;
		return 0;
	}
}
#undef int
using namespace std;
namespace xin1
{
	const int maxn = 10100;
	struct bigint
	{
	    int d[maxn], len;
	    void clean() { while(len > 1 && !d[len-1]) len--; }
	    bigint()     { memset(d, 0, sizeof(d)); len = 1; }
	    bigint(int num)   { *this = num; }
	    bigint(char* num) { *this = num; }
	    bigint operator = (const char* num)
		{
	        memset(d, 0, sizeof(d)); len = strlen(num);
	        for(int i = 0; i < len; i++) d[i] = num[len-1-i] - '0';
	        clean();
	        return *this;
	    }
	    bigint operator = (int num)
		{
	        char s[21]; sprintf(s, "%d", num);
	        *this = s;
	        return *this;
	    }
	    bigint operator + (const bigint& b){
	        bigint c = *this; int i;
	        for (i = 0; i < b.len; i++){
	            c.d[i] += b.d[i];
	            if (c.d[i] > 9) c.d[i]%=10, c.d[i+1]++;
	        }
	        while (c.d[i] > 9) c.d[i++]%=10, c.d[i]++;
	        c.len = max(len, b.len);
	        if (c.d[i] && c.len <= i) c.len = i+1;
	        return c;
	    }
	    bigint operator - (const bigint& b){
	        bigint c = *this; int i;
	        for (i = 0; i < b.len; i++){
	            c.d[i] -= b.d[i];
	            if (c.d[i] < 0) c.d[i]+=10, c.d[i+1]--;
	        }
	        while (c.d[i] < 0) c.d[i++]+=10, c.d[i]--;
	        c.clean();
	        return c;
	    }
	    bigint operator * (const bigint& b)const{
	        int i, j; bigint c; c.len = len + b.len;
	        for(j = 0; j < b.len; j++) for(i = 0; i < len; i++)
	            c.d[i+j] += d[i] * b.d[j];
	        for(i = 0; i < c.len-1; i++)
	            c.d[i+1] += c.d[i]/10, c.d[i] %= 10;
	        c.clean();
	        return c;
	    }
	    bigint operator / (const bigint& b){
	        int i, j;
	        bigint c = *this, a = 0;
	        for (i = len - 1; i >= 0; i--)
	        {
	            a = a*10 + d[i];
	            for (j = 0; j < 10; j++) if (a < b*(j+1)) break;
	            c.d[i] = j;
	            a = a - b*j;
	        }
	        c.clean();
	        return c;
	    }


	    bool operator <(const bigint& b) const{
	        if(len != b.len) return len < b.len;
	        for(int i = len-1; i >= 0; i--)
	            if(d[i] != b.d[i]) return d[i] < b.d[i];
	        return false;
	    }
	    bool operator >(const bigint& b) const{return b < *this;}


	    std::string str() const{
	        char s[maxn]={};
	        for(int i = 0; i < len; i++) s[len-1-i] = d[i]+'0';
	        return s;
	    }
	};

	istream& operator >> (istream& in, bigint& x)
	{
	    std::string s;
	    in >> s;
	    x = s.c_str();
	    return in;
	}

	ostream& operator << (ostream& out, const bigint& x)
	{
	    out << x.str();
	    return out;
	}

	inline short main()
	{
		bigint ans = 0;
		try(i,1,n) ans = ans * 10 + 1;
		ans = ans * (k + 1) * 10;
		ans = ans / 2;
		bigint pow2 = 1;
		try(i,1,n) pow2 = pow2 * k;
		cout<<pow2<<endl;
		ans = ans * pow2;
		cout<<ans / 10<<endl;
		return 0;
	}
}
signed main()
{
	file(hacker2);
	io >> n >> m >> k;
	if(!m) return xin1::main(),0;
	else return xin::main(),0;
}
posted @ 2021-10-06 21:23  NP2Z  阅读(63)  评论(0编辑  收藏  举报