• 12.1


    树树

    solution

    观察发现首先染一个连向叶子结点的点是最优的。

    考虑一下这个点,如果它连向了两个叶子,那么这个点选完先手必赢。

    如果它只连向一个叶子,后手一定会选这个叶子,那么就相当于在原图中删掉了这 两个点。

    那么我们的做法就出来了。 先染色度数为1的点,把相邻的点删掉。 如果在这一步删掉了已经删掉的点(注意不是标记的点),那么先手赢。

    如果最后也没有找到这样的条件,后手赢。

    这样的做法可以通过dfs来实现。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    typedef long long ll;
    const int N=100005;
    inline int read() {
    	int x=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    	return f*x;
    }
    int n;
    int hd[N],to[N<<1],nxt[N<<1],tot;
    inline void add(int x,int y) {
    	to[++tot]=y;nxt[tot]=hd[x];hd[x]=tot;
    }
    
    bool flag;
    bool dfs(int x,int fa) {
    	if(flag) return 0;
    	int res=0;
    	for(int i=hd[x];i;i=nxt[i]) {
    		int y=to[i];
    		if(y==fa) continue;
    		res+=dfs(y,x);
    	}
    	if(res>1) flag=1;//因为多于1个叶子结点肯定有解了
    	if(res==1) return 0;//相当于删点
    	else return 1;//无论是个死胡同还是个散开的树杈先手都能赢
    }
    int main() {
    	int T=read();
    	while(T--)  {
    		n=read();
    		for(int i=1;i<n;i++) {
    			int x=read(),y=read();
    			add(x,y);add(y,x);
    		}
    		if(dfs(1,0)) flag=1;
    		puts(flag?"Illyasviel":"Miyu"); 
    		memset(hd,0,sizeof(hd));
    		tot=0;flag=0;
    	}
    	return 0;
    }
    
    

    网格

    solution

    垃圾构造题

    无解的情况:

    (1)(n=1)(1<t<m);

    (2)(m=1)(1<s<n);

    (3)(n,m,s+t)均为奇数。

    构造如下:

    (1)(s=t=1):

    ![image-20201202195459370](2020.12.1 题解.assets/image-20201202195459370.png)

    (2)(s)(t)均为奇数且(t>1,s<n):

    ![image-20201202195512307](2020.12.1 题解.assets/image-20201202195512307.png)

    (3)(n-s+1,t)均为偶数,(t<m):

    ![image-20201202195529167](2020.12.1 题解.assets/image-20201202195529167.png)

    通过旋转和翻转可以处理其他情况。

    代码咕咕咕了

    我考场水了个20分暴力——输出调试还眼瞎没看到错,然后成功爆零(改好的暴力在下面登不上大雅博客

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #include <cstdlib>
    
    using namespace std;
    
    inline int read(){
    	int x=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
    	return x*f;
    }
    const int N=105;
    int n,m,s,t;
    void baoli() {
    	if(n==1&&m==1){
    		printf("1
    ");return;
    	} 
    	else if(n==1&&m==2) {
     		if(t==1) printf("1
    2
    ");
    		else printf("2
    1
    ");
    		return;
    	}
    	else if(n==1&&m==3) {
    		if(t==1) printf("1
    2
    3
    ");
    		else if(t==3) printf("3
    2
    1
    ");
    		return;
    	}
    	else if(n==2&&m==1) {
    		if(s==1) printf("1 2
    ");
    		else printf("2 1
    ");
    		return;
    	} 
    	else if(n==2&&m==2) {
    		if(s==1&&t==1) printf("1 2
    4 3
    ");
    		else if(s==1&&t==2) printf("2 1
    3 4
    ");
    		else if(s==2&&t==1) printf("2 3
    1 4
    ");
    		else printf("3 4
    2 1
    ");
    		return;
    	}
    	else if(n==2&&m==3) {
    		if(s==1&&t==1) printf("1 2 3
    6 5 4
    ");
    		else if(s==1&&t==2) printf("2 1 6
    3 4 5
    ");
    		else if(s==1&&t==3) printf("3 2 1
    4 5 6
    ");
    		else if(s==2&&t==1) printf("6 5 4
    1 2 3
    ");
    		else if(s==2&&t==2) printf("5 4 3
    6 1 2
    ");
    		else if(s==2&&t==3) printf("4 5 6
    3 2 1
    ");
    		return;		
    	}
    	else if(n==3&&m==1) {
    		if(s==1) printf("1 2 3
    ");
    		else printf("3 2 1
    ");
    		return;
    	}
    	else if(n==3&&m==2) {
    		if(s==1&&t==1) printf("1 2
    4 3
    5 6
    ");
    		else if(s==1&&t==2) printf("2 1
    3 4
    6 5
    ");
    		else if(s==2&&t==1) printf("2 3
    1 4
    6 5
    ");
    		else if(s==2&&t==2) printf("3 2
    4 1
    5 6
    ");
    		else if(s==3&&t==1) printf("3 4
    2 5
    1 6
    ");
    		else if(s==3&&t==2) printf("4 3
    5 2
    6 1
    ");
    		return;			
    	}
    	else if(n==3&&m==3) {
    		if(s==1&&t==1) printf("1 2 9
    4 3 8
    5 6 7
    ");
    		else if(s==1&&t==3) printf("3 2 1
    4 5 6
    9 8 7
    ");
    		else if(s==2&&t==2) printf("3 4 5
    2 1 6
    9 8 7
    ");
    		else if(s==3&&t==1) printf("7 8 9
    6 5 4
    1 2 3
    ");
    		else if(s==3&&t==3) printf("9 8 7
    4 5 6
    3 2 1
    ");
    		return;			
    	}	
    }
    
    int main(){
    	// freopen("grid1.in","r",stdin);
    	// freopen("my.out","w",stdout);
    	int T=read();
    	while(T--) {
    		n=read();m=read();s=read();t=read();
    		if((n&1)&&(m&1)&&((s+t)&1)) {
    			puts("-1");continue;
    		}
    		if(n<=3&&m<=3) baoli();	
    		else {
    			puts("-1");
    		}
    	}
    	return 0;
    }
    

    有手就行

    观察发现只需要把每个游戏拆成一个体积为(1),价值为(a_i)和一个体积为(2),价值为(a_i+b_i)的物品即可覆盖题目中给的条件,做贪心01背包即可。

    神仙拆法:这样达到了所有组合

    单纯暴力

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #include <queue>
    
    using namespace std;
    #define ull unsigned long long
    const int threshold=10000000;
    const int N=2005;
    inline ull read(){
    	ull x=0;char ch=getchar();
    	while(ch<'0'||ch>'9')ch=getchar();
    	while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
    	return x;
    }
    int a[N],b[N],n,m;
    ull k1,k2;
    ull Rand(){
    	ull k3=k1,k4=k2;
    	k1=k4;
    	k3^=(k3<<23);
    	k2=k3^k4^(k3>>17)^(k4>>26);
    	return k2+k4;
    }
    void gen(int n,ull _k1,ull _k2){
    	k1=_k1,k2=_k2;
    	for(int i=1;i<=n;i++){
    		a[i]=Rand()%threshold+1;
    		b[i]=Rand()%threshold+1;
    	}
    }
    ull f[N][N*3][4],ans;
    inline void Max(ull &x,ull y){if(x<y)x=y;}
    int main(){
    	n=read();m=read();k1=read();k2=read();
    	gen(n,k1,k2);
    	for(int i=1;i<=n;i++)
    		for(int j=0;j<=3*i;j++)
    			for(int k=0;k<=3;k++){//上次选了k个 
    				Max(f[i][j][0],f[i-1][j][k]);
    				if(j>=1) Max(f[i][j][1],f[i-1][j-1][k]+a[i]);
    				if(j>=2) Max(f[i][j][2],f[i-1][j-2][k]+a[i]+b[i]);
    				if(j>=3) Max(f[i][j][3],f[i-1][j-3][k]+a[i]+a[i]+b[i]);
    			}
    	for(int i=1;i<=m;i++) 
    		ans^=max(f[n][i][0],max(f[n][i][1],max(f[n][i][2],f[n][i][3])));
    	cout<<ans;
    	return 0;
    }
    
    

    正解:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #include <queue>
    
    using namespace std;
    #define ull unsigned long long
    const int threshold=10000000;
    const int N=15000010;
    inline ull read(){
    	ull x=0;char ch=getchar();
    	while(ch<'0'||ch>'9')ch=getchar();
    	while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
    	return x;
    }
    int a[N],b[N],n,m;
    ull k1,k2;
    ull Rand(){
    	ull k3=k1,k4=k2;
    	k1=k4;
    	k3^=(k3<<23);
    	k2=k3^k4^(k3>>17)^(k4>>26);
    	return k2+k4;
    }
    void gen(int n,ull _k1,ull _k2){
    	k1=_k1,k2=_k2;
    	for(int i=1;i<=n;i++){
    		a[i]=Rand()%threshold+1;
    		b[i]=Rand()%threshold+1;
    	}
    }
    int g[3][N];//表示代价为i的取得了f_i贡献时价值为1/2的取了多少个 
    ull f[N*3],ans,val[3][N];
    bool cmp(ull a,ull b){return a>b;}
    int main(){
    	n=read();m=read();k1=read();k2=read();
    	gen(n,k1,k2);
    	
    	for(int i=1;i<=n;i++) 
    		val[1][i]=a[i],val[2][i]=a[i]+b[i];
    	sort(val[1]+1,val[1]+1+n,cmp);
    	sort(val[2]+1,val[2]+1+n,cmp);
    	g[1][0]=1;g[2][0]=1;
    	for(int i=1;i<=m;i++) {
    		f[i]=f[i-1];
    		g[1][i]=g[1][i-1];g[2][i]=g[2][i-1];
    		if(i-1>=0&&f[i]<=f[i-1]+val[1][g[1][i-1]]) {
    			f[i]=f[i-1]+val[1][g[1][i-1]];
    			g[1][i]=g[1][i-1];g[2][1]=g[2][i-1];
    			g[1][i]=g[1][i-1]+1;
    		}
    		if(i-2>=0&&f[i]<=f[i-2]+val[2][g[2][i-2]]) {
    			f[i]=f[i-2]+val[2][g[2][i-2]];
    			g[1][i]=g[1][i-2];g[2][1]=g[2][i-2];
    			g[2][i]=g[2][i-2]+1;		
    		}
    	}
    	for(int i=1;i<=m;i++) ans^=f[i];
    	cout<<ans;
    	return 0;
    }
    
    

    求余数

    代码先粘一份std

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
     
    #define R register
    #define maxm 110
    #define maxn 1000010
    int pr[maxm], prcnt, mp[maxm], r[maxm];
    int f[26][16], g[2][26][16], aans[maxm][26];
    int pw[maxn], inp[maxn];
    bool vis[maxm], visans[maxn];
    const int mod = 1e9 + 7;
    inline bool cmp(R int a, R int b) {return mp[a] < mp[b];}
    inline int qpow(R int base, R int power)
    {
    	R int ret = 1;
    	for (; power; power >>= 1, base = 1ll * base * base % mod)
    		power & 1 ? ret = 1ll * ret * base % mod : 0;
    	return ret;
    }
    struct Q {int n, m;} qq[510];
    int main()
    {
    	R int T; scanf("%d", &T);
    	for (R int i = 2; i <= 100; ++i)
    	{
    		if (!vis[i]) pr[++prcnt] = mp[i] = i;
    		for (R int j = 1; j <= prcnt && i * pr[j] <= 100; ++j)
    		{
    			vis[i * pr[j]] = 1;
    			mp[i * pr[j]] = mp[i];
    			if (i % pr[j] == 0) break;
    		}
    	}
    	R int maa = 0;
    	for (R int i = 1; i <= T; ++i) scanf("%d%d", &qq[i].n, &qq[i].m), maa < qq[i].n ? maa = qq[i].n : 0;
    	pw[0] = 1;
    	for (R int i = 1; i <= maa; ++i) pw[i] = 1ll * pw[i - 1] * i % mod;
    	inp[maa] = qpow(pw[maa], mod - 2);
    	for (R int i = maa; i; --i) inp[i - 1] = 1ll * inp[i] * i % mod;
     
    	for (R int TT = 1; TT <= T; ++TT)
    	{
    		R int n = qq[TT].n, m = qq[TT].m, tot = 0;
    		R int lim = m < 25 ? m : 25;
    		if (!visans[m])
    		{
    		visans[m] = 1;
    		for (R int i = 2; i <= m; ++i) r[i] = i;
    		std::sort(r + 2, r + m + 1, cmp);
     
    		memset(f, 0, sizeof (f));
    		memset(g, 0, sizeof (g));
    		g[0][0][0] = 1;
    		for (R int i = 2; i <= m; ++i)
    		{
    			if (mp[r[i]] < 10 || (mp[r[i]] != mp[r[i - 1]]))
    			{
    				tot ^= 1;
    				memset(f, 0, sizeof (f));
    				memset(g[tot], 0, sizeof (g[tot]));
    			}
     
    			R int tmp = r[i], tS = 0;
    			if (tmp % 2 == 0) tS |= 1;
    			if (tmp % 3 == 0) tS |= 2;
    			if (tmp % 5 == 0) tS |= 4;
    			if (tmp % 7 == 0) tS |= 8;
    			
    			R int pS = ~tS & 15;
    
    			for (R int j = lim; j; --j)
    			{
    				R int *fij = f[j], *gij = g[tot ^ 1][j - 1];
    				for (R int S = pS; S; S = (S - 1) & pS)
    					(fij[S | tS] += gij[S]) %= mod;
    				(fij[tS] += gij[0]) %= mod;
    			}
     
    			if (i == m || mp[r[i + 1]] < 10 || mp[r[i + 1]] != mp[r[i]])
    			{
    				for (R int j = 0; j <= lim; ++j)
    				{
    					R int *gij = g[tot][j], *gij1 = g[tot ^ 1][j], *fij = f[j];
    					for (R int S = 0; S < 16; ++S)
    						gij[S] = (gij1[S] + fij[S]) % mod;
    				}
    			}
    		}
    		for (R int i = 0; i <= lim; ++i) for (R int S = 0; S < 16; ++S) (aans[m][i] += g[tot][i][S]) %= mod;
    		}
    		R int ans = 0;
    		for (R int i = 0; i <= lim && i <= n; ++i)
    		{
    			R int Cp = 1ll * pw[n] * inp[n - i] % mod;
    			ans = (ans + 1ll * aans[m][i] * Cp) % mod;
    		}
    		printf("%d
    ", ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    solr部署长命版后继
    reiserfs相关
    sqlite in python
    查看文件系统
    https://wiki.fourkitchens.com/dashboard.action这个技术wiki不错
    gvim菜单显示问题
    linux tips
    solr部署一气呵成版,让你多活两天
    挺好玩的C语句
    hardy ubuntu source list
  • 原文地址:https://www.cnblogs.com/ke-xin/p/14077499.html
Copyright © 2020-2023  润新知