数字统计(模拟)

思路

没有什么好讲的,纯纯模拟,记得数位分离。

代码

#include <bits/stdc++.h>
using namespace std;

int main(){
	freopen("tj.in","r",stdin);
	freopen("tj.out","w",stdout);
	int l,r;
	int cnt=0;
	cin >>l>>r;
	for(int i=l;i<=r;i++){
		int res=i;
		while(res){
			if(res%10==2) cnt++;
			res=(res-(res%10))/10;
		}
	}
	cout <<cnt;
	return 0;
}

乒乓球(模拟)

思路没想到的原因

数组开小了,以后注意数据范围

思路

直接模拟,满足条件就放入数组里。最后输出注意格式。

代码

#include <bits/stdc++.h>
using namespace std;

const int tt=1e6+10;
int a[tt],b[tt],c[tt],d[tt];

int main(){
	freopen("pingpong.in","r",stdin);
	freopen("pingpong.out","w",stdout);
	char z;
	int i=1;
	int j=1;
	int cnt=0;
	for(;;cnt++){
		cin >>z;
		if(z=='E'){
			break;
		}else{
			if(z=='W'){
				a[i]++;
				c[j]++;
			}else{
				b[i]++;
				d[j]++;
			}
			if((a[i]>=11||b[i]>=11)&&(a[i]-b[i]>=2||b[i]-a[i]>=2)){
				i++;
			}
			if((c[j]>=21||d[j]>=21)&&(c[j]-d[j]>=2||d[j]-c[j]>=2)){
				j++;
			}
		}
	}
	for(int k=1;k<=i;k++){
		cout <<a[k]<<":"<<b[k]<<endl;
	}
	cout <<endl;
	for(int k=1;k<=j;k++){
		cout <<c[k]<<":"<<d[k]<<endl;
	}
	return 0;
}

侦探推理(模拟)

思路没想到的原因

模拟的能力还需加强,一遇到大模拟就不会写。

思路

本题是一个超~~~~~~大的模拟!!!

将证词和人分开处理,更简单直接。可以用map将对字符串的处理转为对数的处理,进一步简化代码。

将证词分成xxyy是凶手,xxyy不是凶手,xx说今天是星期几。

每句证词都可分为真话和假话,关于凶手和星期,共有四类,直接用基本的循环就可以了。

接着枚举可能的星期和凶手,判断是否可行。

需注意判断checkcheck函数。

代码

#include <bits/stdc++.h>
using namespace std;

string mz[110];
int state[110],fh=0,hh=0;
bool st[110];
pair<int,string>zc[110];
int m,n,p;

string week[]={
	"Today is Monday.",
	"Today is Tuesday.",
	"Today is Wednesday.",
	"Today is Thursday.",
	"Today is Friday.",
	"Today is Saturday.",
	"Today is Sunday."
};

int get_id(string s){
	for(int i=1;i<=m;i++){
		if(s==mz[i]) return i;
	}
	return -1;
}

int judge(int day,int bad,int now,string s){
	if(s=="I am guilty.") return now!=bad;
	if(s=="I am not guilty.") return now==bad;
	for(int i=1;i<=m;i++){
		if(s==mz[i]+" is guilty."){
			return i!=bad;
		}
	}
	for(int i=1;i<=m;i++){
		if(s==mz[i]+" is not guilty."){
			return i==bad;
		}
	}
	for(int i=0;i<7;i++){
		if(s==week[i]) return i!=day;
	}
	return -1;
}

bool check(int day,int bad){
	fh=hh=0;
	memset(state,-1,sizeof state);
	for(int i=1;i<=p;i++){
		if(judge(day,bad,zc[i].first,zc[i].second)==1){
			if(state[zc[i].first]==-1) state[zc[i].first]=1;
			if(state[zc[i].first]==0) return false;
		}else if(judge(day,bad,zc[i].first,zc[i].second)==0){
			if(state[zc[i].first]==-1) state[zc[i].first]=0;
			if(state[zc[i].first]==1) return false;
		}
	}
	for(int i=1;i<=m;i++){
		if(state[i]==1) hh++;
		else if(state[i]==-1) fh++;
	}
	return hh<=n&&n<=hh+fh;
}

int main(){
	freopen("zt.in","r",stdin);
	freopen("zt.out","w",stdout);
	int cnt=0;
	string op="";
	cin >>m>>n>>p;
	for(int i=1;i<=m;i++){
		cin >>mz[i];
	}
	for(int i=1;i<=p;i++){
		string first,second;
		cin >>first;
		first.erase(first.end()-1);
		getline(cin,second);
		second.erase(second.begin());
		zc[i]={get_id(first),second}; 
	}
	for(int i=1;i<=m;i++){
		for(int day=0;day<7;day++){
			if(check(day,i)&&st[i]==0){
				cnt++;
				op=mz[i];
				st[i]=1;
			}
		}
	}
	if(cnt>1){
		cout <<"Cannot Determine";
	}else if(cnt==1){
		cout <<op;
	}else{
		cout <<"Impossible";
	}
	return 0;
}

游戏(DP&前缀和)

思路没想到的原因

没有转化一些看似很复杂的题面部分,下次应该将复杂的题面联系到自己学过的知识并加以运用。

思路

因为输入的数据是一个环,所以我们要破环为链。怎样破环为链呢?很简单,在输入的时候复制一遍在数组后面:a[i+n]=a[i]。这样问题就转化成了线段型的模型。

状态表示:

  • f[l][r][i]f[l][r][i]表示所有将a[l r]a[l~r]分割成ii部分的方案的最大乘积;
  • g[l][r][i]g[l][r][i]表示所有将a[l...r]a[l...r]分割成ii部分的方案的最小乘积。
  • s[i]s[i]表示a[i]a[i]数组的前缀和。

状态计算:

$f[l][r][k]=max(f[l][r][k],f[l][t-1][k-1]*op(s[r]-s[t-1]))$ $g[l][r][k]=min(g[l][r][k],g[l][t-1][k-1]*op(s[r]-s[t-1]))$

还有要记得避免负数的情况,可以用一个函数来写,简洁明了。

代码

#include <bits/stdc++.h>
#define int long long
using namespace std;

const int tt=110;
int a[tt],f[tt][tt][tt],s[tt*2],g[tt][tt][tt];

int op(int n){
	while(n<0) n+=10;
	return n%10;
}

signed main(){
	freopen("game.in","r",stdin);
	freopen("game.out","w",stdout);
	memset(g,0x2f2f2f2f,sizeof g);
    int n,m;
    cin >>n>>m;
    for(int i=1;i<=n;i++){
        cin >>a[i];
        a[i+n]=a[i];
    }
    for(int i=1;i<=n*2;i++){
    	s[i]=s[i-1]+a[i];
	}
	for(int len=1;len<=n;len++){
	    for(int l=1;l<=n+1;l++){
	        int r=l+len-1;
	        f[l][r][1]=op(s[r]-s[l-1]);
	        g[l][r][1]=op(s[r]-s[l-1]);
	        for(int k=2;k<=m;k++){
	            for(int t=l+1;t<r;t++){
	            	f[l][r][k]=max(f[l][r][k],f[l][t-1][k-1]*op(s[r]-s[t-1]));
	            	g[l][r][k]=min(g[l][r][k],g[l][t-1][k-1]*op(s[r]-s[t-1]));
				}
	        }
	    }
	}
	int max_n=0,min_n=0x2f2f2f2f;
	for(int i=1;i<=n+1;i++){
		max_n=max(f[i][i+n-1][m],max_n);
		min_n=max(min(g[i][i+n-1][m],min_n),0ll);
	}
	cout <<min_n<<endl<<max_n;
    return 0;
}

谢谢