自定义函数递推的表达
对于:
1 2
2 8
3 26
... ...
8=2*3+2;
26=8*3+2...
除了第一行,其余行都是f(n-1)*3+2;
int f(int x){
if(x==1)return 2;
else{
return f(x-1)*3+2;
}
}
四舍五入的表达
printf("%.0f", len(sum)+0.1 );
printf("%.0f", len(sum)+0.000001 );
均可
侦探推理
题目描述
明明同学最近迷上了侦探漫画《柯南》并沉醉于推理游戏之中,于是他召集了一群同学玩推理游戏。游戏的内容是这样的,明明的同学们先商量好由其中的一个人充当罪犯(在明明不知情的情况下),明明的任务就是找出这个罪犯。接着,明明逐个询问每一个同学,被询问者可能会说:
证词中出现的其他话,都不列入逻辑推理的内容。
明明所知道的是,他的同学中有N个人始终说假话,其余的人始终说真。
现在,明明需要你帮助他从他同学的话中推断出谁是真正的凶手,请记住,凶手只有一个!
输入描述:
输入由若干行组成,第一行有二个整数,M(1≤M≤20)、N(1≤N≤M)和P(1≤P≤100);M是参加游戏的明明的同学数,N是其中始终说谎的人数,P是证言的总数。接下来M行,每行是明明的一个同学的名字(英文字母组成,没有主格,全部大写)。 往后有P行,每行开始是某个同学的名宇,紧跟着一个冒号和一个空格,后面是一句证词,符合前表中所列格式。证词每行不会超过250个字符。 输入中不会出现连续的两个空格,而且每行开头和结尾也没有空格。
输出描述:
如果你的程序能确定谁是罪犯,则输出他的名字;如果程序判断出不止一个人可能是罪犯,则输出 Cannot Determine;如果程序判断出没有人可能成为罪犯,则输出 Impossible。
输入
3 1 5
MIKE
CHARLES
KATE
MIKE: I am guilty.
MIKE: Today is Sunday.
CHARLES: MIKE is guilty.
KATE: I am guilty.
KATE: How are you??
输出
MIKE
using namespace std;
int m, n, p;
string name[30];
string s[110];
int a[30]; //a=1 说真话的人,a=2的时候是说假话的人 a=0还不知道是真是假
int cnt[4]; //cnt[1]是说真话的人数, cnt[2]是说假话的人数
int xiongshou[30];
string week[8] = {"","Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Satursday", "Sunday"};
int dijigeren(string s) //s这个人的名字是谁的名字
{
for (int i = 1; i <= m; i++)
if (s == name[i]) return i;
return 0;
}
int judge(int g, int d, string s)
//今天星期d,凶手是g的情况下s这句话是真话1还是假话2还是废话0
{
int pos = s.find(":");//7
if(s.find("I am guilty.") != string::npos) {
if (name[g] == s.substr(0, pos)) return 1;
else return 2;
}
if(s.find("I am not guilty.") != string::npos) {
if (name[g] == s.substr(0, pos)) return 2;
else return 1;
}
if(s.find(" is guilty.")!= string::npos){
int t = s.find(" is guilty.");//13
string tmpname = s.substr(pos+2, t-1 - (pos+2)+1);
int num = dijigeren(tmpname);
if (num == 0) return 0; //找不到这个人,说明说的是废话
if (num == g) return 1;
return 2;
}
if(s.find(" is not guilty.")!= string::npos){
int t = s.find(" is not guilty.");
string tmpname = s.substr(pos+2, t-1 - (pos+2)+1);
int num = dijigeren(tmpname);
if (num == 0) return 0;
if (num == g) return 2;
return 1;
}
if (s.find("Today is ")!= string::npos){
int t = s.find("Today is ") + 9; //找到的是T这个位置,但是现在要标记is后的空格这个位置
string day = s.substr(t, s.length()-t-1); //减去.这个位置
int num = 0;
for (int i = 1; i <= 7; i++)
if (day == week[i]){
num = i; break;
}
if (num == 0) return 0;//找不到是星期几,说的是废话
if (num == d) return 1;
return 2;
}
return 0;
}
int main()
{
cin>>m>>n>>p;
for (int i = 1; i <= m; i++)
cin >> name[i]; // string s中s就相当于一个一维数组,所以name[i]相当于二维数组,
//name[1]存储MIKE,name[2]存储CHARLES
// cout <<name[1]<<endl;
// cout<<judge(1, 1, "MIKE: Today is day.")<<endl;
getline(cin, s[0]);//把KATE后面的回车读走
//在使用 cin 后若要使用 getline() 必须要把前面cin遗留的结束符处理掉,
//解决方法为:在使用getline()之前,加入一行getline()来处理cin留下的结束符
for (int i = 1; i <= p; i++)
getline(cin, s[i]);
for (int g = 1; g <= m; g++){ //凶手
for (int d = 1; d <= 7; d++) //星期几
{
memset(a, 0, sizeof(a));//对数组归零
cnt[1]=cnt[2]=0;
int flag = 1;
for(int i = 1; i <= p; i++)
{
int tmp = judge(g, d, s[i]);
int num = dijigeren(s[i].substr(0, s[i].find(":") ) );//如MIKE:就是从0到4
//s[i].find(":")==4,表示从M开始读4个字符
// printf("today=%d,i=%d,shuohuaderen=%d, zhengjia=%d\n", d,i,num,tmp);
if(tmp != 0 && a[num] != 0 && tmp != a[num]) {
flag = 0; break; //若一个人说了真话但是判断他是说假话的人,
//则说明之前给他的假设不成立即g=? d=?这个判断不成立,
//可break掉把g或d换个数字来试,所以才有if(flag == 0) continue;
}
if(tmp != 0 && a[num] == 0) {
a[num] = tmp; cnt[tmp]++;//a[num]==0说明之前未知这个人是说真话还是假话
//现在知道了,就把tmp赋给a[]
}
}
if(flag == 0) continue;
if (cnt[2] > n || cnt[2]+(m-cnt[1]-cnt[2]) < n) break;//说假话的人数>n
//或假设说废话的人全是说假话的,再加上确认是说假话的还<n 则不满足题意
xiongshou[g] = 1;//把可疑的凶手都标记起来
}
}
int cnt = 0, pos = 0;
for(int i = 1; i <= m; i++)
{
if (xiongshou[i] == 1) cnt++,pos=i;
}
if (cnt == 0) cout<<"Impossible";
if (cnt == 1) cout<<name[pos];
if (cnt > 1 ) cout<<"Cannot Determine";
return 0;
}
高精度的表达
两数相加
如:
514
495
1009
#include<bits/stdc++.h>
using namespace std;
int main(){
string s,s1;
cin>>s>>s1;
int a[1000],b[1000],c[1000]={0} ;
int lena=s.length(),lenb=s1.length() ;
int len=max(lena,lenb);
for(int i=lena-1,j=1;i>=0;i--,j++){//字符串是从s[0]开始
a[j]=s[i]-'0';
}
for(int i=lenb-1,j=1;i>=0;i--,j++){//字符串是从s[0]开始
b[j]=s1[i]-'0';
}
for(int i=1;i<=len;i++){ //从个位开始加
c[i]=c[i]+a[i]+b[i];//c[i]从1开始后面不会混乱 ,可能前一位给了后一位某个数值所以要加c[i]
c[i+1]=c[i]/10;
c[i]=c[i]%10;
}
if(c[len+1]) //最后一位会不会进位
len++;
for(int i=len;i>=1;i--){
printf("%d",c[i] );
}
return 0;
}
两数相减
#include<bits/stdc++.h>
using namespace std;
int t,a[1000],b[1000];
void trans(string s,int a[] ){
for(int i=1,j=s.length()-1;j>=0;j--,i++){
a[i]=s[j]-'0';
}
}
bool judge(string s,string s1){ //判断两个数谁大谁小
int lena=s.length(), lenb=s1.length() ;
if(lena>lenb) return 1;//比较数位长度
if(lena<lenb) return 0;
if(s>=s1) return 1;//数位相同时从高位开始比较字典序
return 0;
}
void jian(int a[],int b[],int lena,int lenb ){
int c[1000]={0};
int len=max(lena,lenb);
for(int i=1;i<=len;i++){
c[i]=c[i]+a[i]-b[i];
if(c[i]<0){
c[i]=c[i]+10;
c[i+1]--;
}
}
while(c[len]==0)//防止出现类似001
len--;
for(int i=len;i>=1;i--)
printf("%d",c[i] );
}
int main(){
string s,s1;
cin>>s>>s1;//用字符串输入可直接知道长度(位数)
int lena=s.length(), lenb=s1.length() ;
trans(s,a);//把字符串转换成数组
trans(s1,b);//数组传递的是首地址,形参改变实参也改变了
if(judge(s,s1))
jian(a,b,lena,lenb);
else{
printf("-");jian(b,a,lena,lenb);//如1-799 统一变成大数减小数,再添个负号
}
return 0;
}
两数相乘
#include<bits/stdc++.h>
using namespace std;
int t,a[1000],b[1000];
void trans(string s,int a[] ){
for(int i=1,j=s.length()-1;j>=0;j--,i++){
a[i]=s[j]-'0';
}
}
void cheng(int a[],int b[] ,int lena, int lenb){
int c[1000]={0},len=lena+lenb ;//三位数乘三位数最多是六位数(999*999),一般是三位数
for(int i =1;i<=lena;i++){ //a[1]*b[1]是结果的第i+j-1位
for(int j=1;j<=lenb;j++){
c[i+j-1]+=a[i]*b[j];//要加上它本身,因为后面的进位可能已经给该位赋值了
}
}
for(int i=1;i<=len;i++){
c[i+1]+=c[i]/10;//处理进位
c[i]=c[i]%10;
}
if(c[len]==0)len--;//结果可能只是五位数(若是三位数相乘)
for(int k=len;k>=1;k--)
printf("%d",c[k] );
}
int main(){
string s,s1;
cin>>s>>s1;//用字符串输入可直接知道长度(位数)
int lena=s.length(), lenb=s1.length() ;
trans(s,a);//把字符串转换成数组
trans(s1,b);//数组传递的是首地址,形参改变实参也改变了
cheng(a,b,lena,lenb);
return 0;
}
两数相除
1、高精度÷低精度(int)
#include<bits/stdc++.h>
using namespace std;
int t,a[1000],b[1000];
void chu(string s,int b ){
int c[1000]={0};
int len=s.length(); //被除数有几位就要进行几次运算
int rest=0;
for(int i=0;i<len;i++){ //string是从s[0]开始读入
rest = rest*10+s[i]-'0';
c[i]=rest/b;
rest=rest%b;
}
int pos=0;
while(c[pos]==0)
pos++;
for(int i=pos;i<len;i++)
printf("%d",c[i] );
printf("\n%d",rest);//输出余数
}
int main(){
string s;
int b;
cin>>s>>b;//用字符串输入可直接知道长度(位数)
chu(s,b); //默认a>b
return 0;
}