斐波那契数
先把小于题目数据范围的斐波那契数找到,放到数组里。接下来从大往小的不断地去找,就可以了。
#include
#include
using namespace std;
typedef long long ll;
const int maxn = 1e3 + 10;
const int mod = 1e9 + 7;
int Fib[maxn];
int main(){
int cnt = 1;
Fib[0] = 0;
Fib[1] = 1;
for (int i = 2; Fib[i - 1] <= 100000; i++,cnt++){
Fib[i] = Fib[i - 1] + Fib[i - 2];
}
int t;
scanf("%d", &t);
while (t--){
int n,ans=0;
scanf("%d", &n);
for (int i = 26; i >= 1; i--){
if (n >= Fib[i])n -= Fib[i], ans++;
}
printf("%d\n", ans);
}
return 0;
}
打麻将:
是有多个解决方法的。最开始我是想的搜索,这部分代码是刘越洋同学写的。
代码如下:
#include
#include
#include
using namespace std;
bool ok=0;
bool vis[20];
char a[20];
int d[20][5];
int ttt[11];
void dfs(int cur,char *str,int cnt){
if(cur>12)return;
if(cur==12&&cnt==4){
int a=0,b=0;
for(int i=1;i<=14;i++)if(!vis[i]){vis[i]=true,a=i;break;}
for(int i=1;i<=14;i++)if(!vis[i]){vis[i]=true,b=i;break;}
if(str[a]==str[b]&&(str[a]!=' '&&str[b]!=' '))
ok=true;
vis[a]=vis[b]=false;
return ;
}
for(int i=1;i<=12&&!ok;i++)
if(!vis[i])
for(int j=i+1;j<=13&&!ok;j++)
if(!vis[j])
for(int k=j+1;k<=14&&!ok;k++){
if(!vis[k])
if((str[i]==str[j]&&str[j]==str[k])||(str[i]+1==str[j]&&str[j]+1==str[k]))
{
vis[i]=vis[j]=vis[k]=true;
dfs(cur+3,str,cnt+1);
vis[i]=vis[j]=vis[k]=false;
}
}
}
int main(){
int t;
scanf("%d",&t);
while(t--){
int tt_=0;
ok=false;
memset(ttt,0,sizeof(ttt));
scanf("%s",&a[1]);
for(int i=1;i<=14;i++){
ttt[a[i]-'0']++;
if(ttt[a[i]-'0']>4)
{
printf("The data is error!\n");
tt_=1;
break;
}
}
if(tt_)continue;
sort(a+1,a+15);
dfs(0,a,0);
if(!ok)printf("NO\n");
else printf("YES\n");
}
return 0;
}
很多没有接触过dfs的同学可能不会;蓝桥杯又被称为“暴力杯”。真的比赛,即使不会,也要试试,写个暴力的方法,得到一部分分;
我担心难度太大,就尝试暴力去写。
希望更多的人能写出来。首先把所有的刻子或顺子枚举出来,一共是16个。123 234 345 456 567 678 789 111 222 333
444 555 666 777 888 999。所有的对子一共是这几个11 22 33 44 55 66 77 88 99.那么所有的可能,暴力去找的话就是
四个for遍历所有的刻子或顺子,一个for遍历对子。复杂度大概是161616169=589824;还没算完。
即使遍历到了,你还要去和给的样例去比较,这个比较也是很麻烦的。最终完全没有优化的复杂度是很高的。
这部分代码如下:
#pragma GCC optimize(2)
#include
using namespace std;
//typedef long long int ll;
//#define mod 1000000007
//const ll maxnum = 1000000000000000000;
//bool cmp(ll a, ll b)
//{
// return a2 || sumab[i] == 1 || sumab[i] < 0)
{
flag = 0;
}
sumab[i] = sumstr[i];
}
return flag;
}
int main()
{
#ifdef LOCAL
freopen("D:/input.in", "r", stdin);
#endif
//freopen("D:/out.out", "w", stdout);
int suma = 0;
int sumb = 0;
int T;
cin >> T;
while (T--)
{
memset(sumstr, 0, sizeof(sumstr));
memset(sumab, 0, sizeof(sumab));
memset(str, 0, sizeof(str));
getchar();
scanf("%s", &str);
//cin >> str;
int lenstr = strlen(str);
for (int i = 0; i < lenstr; i++)
{
sumstr[str[i] - '0']++;
sumab[str[i] - '0']++;
}
int flag = 0;
int sumshoupai = 0;
for (int i = 1; i < 10; i++)
{
if (sumstr[i] >= 5)
flag = 1;
sumshoupai += sumstr[i];
}
if (sumshoupai != 14 || flag == 1)
{
cout << "The data is error!" << endl;
continue;
}
flag = 0;
for (int i = 0; i < 16; i++)
{
for (int j = 0; j < 16; j++)
{
for (int k = 0; k < 16; k++)
{
for (int l = 0; l < 16; l++)
{
if (check(a[i], a[j], a[k], a[l]) == 1)
{
flag = 1;
break;
}
}
if (flag == 1)
break;
}
if (flag == 1)
break;
}
if (flag == 1)
break;
}
if (flag == 1)
{
suma++;
cout << "YES" << endl;
}
else
{
sumb++;
cout << "NO" << endl;
}
}
//cout << suma + sumb << endl;
//cout << suma << ' ' << sumb << endl;
return 0;
}
后来发现这个题直接贪心就可以了。。复杂度非常低;这个题本来数据是很完整的,把所有手牌的可能都找到了,大约11万。
刚才的两个程序,在测试时,一秒钟大概只能测800或者更低。测试数据给了200个样例。贪心的策略可以把所有样例都一秒内算出来;
贪心的策略是 先找到一个对子,然后把这个对子从手牌里删去,看手牌里有没有四个顺子或刻子;附代码:
#include
#include
using namespace std;
typedef long long ll;
char str[20];
int a[15];
int num[15];
void huanyuan(int q[15])
{
for (int i = 1; i <= 9; i++)
{
q[i] = a[i];
}
}
int main()
{
#ifdef LOCAL
freopen("D:/2.in", "r", stdin);
#endif
//freopen("D:/out.out", "w", stdout);
int t;
cin >> t;
while (t--)
{
memset(str, 0, sizeof(str));
memset(a, 0, sizeof(a));
getchar();
scanf("%s", &str);
/*if (t == 4)
cout << str << endl;*/
for (int i = 0; i < strlen(str); i++)
{
a[str[i] - '0']++;
}
int flag = 0;
for (int i = 1; i < 10; i++)
{
if (a[i]>=5)
{
printf("The data is error!\n");
flag = 1;
break;
}
}
int ans = 0;
for (int i = 1; i < 10; i++)
{
huanyuan(num);
ans = 0;
if (num[i] >= 2)
{
num[i] -= 2;
for (int j = 1; j <= 9; j++)
{
if (num[j] < 3&&num[j]>0)
{
if (num[j] <= num[j + 1] && num[j] <= num[j + 2])
{
ans += num[j];
num[j + 1] -= num[j];
num[j + 2] -= num[j];
num[j] -= num[j];
}
else {
break;
}
}
else if(num[j] == 3){
if (num[j + 1] >= num[j] && num[j + 2] >= num[j])
{
ans += 3;
num[j] -= 3;
num[j+1] -= 3;
num[j+2] -= 3;
}
else {
num[j] -= 3;
ans++;
}
}
else if (num[j] == 4)
{
ans++;
num[j] -= 3;
if (num[j + 1] >= 1 && num[j + 2] >= 1)
{
ans++;
num[j] --;
num[j + 1]--;
num[j + 2]--;
}
else {
break;
}
}
}
if (ans == 4)
{
printf("YES\n");
flag = 1;
break;
}
}
}
if (flag == 0)
{
printf("NO\n");
}
}
return 0;
}
代码非常丑陋,具体细节,私聊;