1. 程式人生 > >1304 A&&B

1304 A&&B

蒟蒻的一篇題解

原題傳送門:A

評測記錄(http://topoi.top/status/show/41886

#include<bits/stdc++.h>
#define f(i,j,n) for(register int i=j;i<=n;i++)
using namespace std;
int n;
struct node {
	int x;
	int y;
} a[1<<4];//結構體記錄甜度酸度。
int ans=INT_MAX;
//通常比較最小值就用最大值 INT_MAX顧名思義int最大值21...其實就是本蒟蒻背不出來QAQ
bool vis[1<<4];//n<=10 用位運算可以好(zhuang)看(bi)
//請忽略下面這段
void openfile() {
	freopen("perket.in","r",stdin),freopen("perket.out","w",stdout);
}
void closefile() {
	fclose(stdin),fclose(stdout);
}
void dfs(int x,int y,int z) {
	//cout<<x<<" "<<y<<" "<<z<<endl;
	if(z!=0) ans=min(ans,abs(x-y));//第一次不用更新不然每次出來都是1(劃掉
	if(z==n) return;//如果搜到n了就返回
	f(i,1,n)
	if(!vis[i])//判斷
		vis[i]=true,//打標記
		       dfs(x*a[i].x,y+a[i].y,z+1),//往下搜
		       vis[i]=false;//回溯
}
int main() {
	ios::sync_with_stdio(false);//關閉同步流
	//openfile();
	memset(vis,false,sizeof(vis));//初始化
	cin>>n;
	f(i,1,n) cin>>a[i].x>>a[i].y;//輸入甜度 酸度
	dfs(1,0,0);//深搜
	cout<<ans<<endl;//輸出QAQ
	//closefile();
	return 0;
}

原題傳送門:B

評測記錄(http://topoi.top/status/show/42016

#include<bits/stdc++.h>
#define f(i,j,n) for(int i=j;i<=n;i++)
using namespace std;
typedef long long ll;
const int N=100000+5;
int n,k;
int m,g[N];
ll f[N][30];
inline ll read() {//快讀 優化1
	ll x=0;
	int t=1;
	char ch=getchar();
	while((ch<'0'||ch>'9') and ch!='-') ch=getchar();
	if(ch=='-') t=-1,ch=getchar();
	while(ch<='9' and ch>='0') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
	return t*x;
}
bool dfs(int t,int x,int tem) {//此處懶得false true(劃掉)
	if(!x) return tem==n;//x==0 優化2
	x--;//如果x!=0 那麼x--; 接著搜
	while (1) {
		if(t+x>m) return 0;//如果已使用+未使用>總約數個數 那麼返回 優化3
		if(f[t][x]>n || f[t][x]*tem>n) return 0;
        //如果此時的值已經大於n或者下個大於n 返回 優化4
		if(dfs(t+1,x,tem*g[t])) return 1;//如果可行直接返回
		t++;(已使用++)
	}
}
int main() {
	int QAQ=read();
    //QAQ QAQ QAQ...
	while (QAQ--) {
		n=read(),k=read();
		if((n==1 and k>=2) or (n>=3 and k>=n)) {
			printf("NIE\n");
			continue;
		}
		if(k<=2) {
			printf("TAK\n");
			continue;
		}//優化5 特判...咳咳 因為1和2是可以特判的 通常很多(逃)
		int t;
		m=0;
		for (t=1; t*t<n; t++)
        //算約數
			if (n%t==0) g[++m]=t,g[++m]=n/t;
		if (t*t==n) g[++m]=t;
		sort(g+1,g+m+1);//排序
		ll tem=1;
		for (int i=1; i<=m; i++,tem=1)//迴圈+初始化
			for (int j=0; j<k and i+j<=m; f[i][j++]=tem)
				if (tem<=n) tem*=g[i+j];
		if (dfs(1,k,1)) puts("TAK");//puts效率>printf 優化6(逃)
		else puts("NIE");
	}
	return 0;
}