坐标:BUPT;OJ:Excited OJ
%%%AK大佬,感觉这次AK的人均OI选手……
还是刷题不够Orzzzz
#include
#include
#include
#include
#include
#define For(i,a,b) for (int i=(a); i<=(b); ++i)
typedef long long ll;
ll alpha(ll x)
{
if (x/10==0)
return x;
else
{
ll sum=1;
while (x!=0)
{
if (x%10!=0)
sum*=x%10;
x/=10;
}
return alpha(sum);
}
}
int main()
{
ll n;
scanf("%lld",&n);
printf("%lld",alpha(n));
return 0;
}
//4018224312
PS:感觉这道递归考的不难,但是还是有细节的
“贴邮票” 这三个字让我一阵恶寒……但是这次并非三循环暴力解法
#include
#include
#include
#include
#include
#define For(i,a,b) for (int i=(a); i<=(b); ++i)
void swap(int *a, int *b)
{
int t=*a; *a=*b; *b=t;
}
void sort(int a[], int n)
{
For(i,1,n-1)
{
For(j,i+1,n)
{
if (a[j]>a[i])
swap(&a[j],&a[i]);
}
}
}
int main()
{
int m,n;
scanf("%d%d",&m,&n);
int a[n];
For(i,1,n)
scanf("%d",&a[i]);
sort(a,n);
int cnt=0,sum=0;
For(i,1,n)
{
sum+=a[i];
cnt++;
if (sum>=m)
break;
}
printf("%d",cnt);
return 0;
}
/*
100 5
10 20 30 40 50
*/
在此选择了选择排序的方法,其实只需每次求出最大值即可,算是贪心思想?
PS:好吧让我们期待下一次的贴邮票
#include
#include
#include
#include
#include
#define For(i,a,b) for (int i=(a); i<=(b); ++i)
int main()
{
int n;
scanf("%d",&n);
int a[n][n];
int cnt=0;
For(i,0,n-1)
{
int x=-1,y=i;
while(x!=y)
{
x++;
cnt++;
a[y][x]=cnt;
}
while(y!=0)
{
y--;
cnt++;
a[y][x]=cnt;
}
}
For(i,0,n-1)
{
For(j,0,n-1)
printf("%d ",a[i][j]);
printf("\n");
}
return 0;
}
PS:没什么技术含量,但是我把x、y打反了orz
这个题我停止了思考……其实可以打的更简洁
(其实是一个multimap) 乱打就完了
update
打得实在是太丑了,重置了一下:
#include
#include
#define For(i,a,b) for (int i=(a); i<(b); ++i)
char card[]="3456789TJQKA2BR";
int num[]={1,1,1,2,2,2,3,3,4,5,6,8,10,15,20};
int len=15; //¹²15¸öÔªËØ
int main()
{
int n;
scanf("%d",&n);
char a[n][25];
For(i,0,n)
scanf("%s",a[i]);
int sum[n];
For(i,0,n)
{
int s=strlen(a[i]);
sum[i]=0;
For(j,0,s)
For(k,0,len)
if (a[i][j]==card[k])
{
sum[i]+=num[k];
break;
}
}
For(i,0,n)
{
int max=0,t=0;
For(j,0,n)
if (sum[j]>max)
{
max=sum[j];
t=j;
}
sum[t]=0;
printf("%s\n",a[t]);
}
return 0;
}
/*
5
QQQ56AJR9Q
T5RJJJT82
RKT8J6QT5A
5T9RJ9J6B
9994A7QRBQ
*/
“二分答案” 应该说是本题的正解,复杂度为 O(nlogn)
然而蒟蒻本蒻竟然一直在想分治……Orzzzzz
update
今晚打完了Atcoder想用这篇博客里的代码提交一下,结果发现这道题编译不给过,仔细一看原来打成了C++……
经过修改,C语言的版本也能A了,只是一些语法上的问题,不过还是放在下面,Cpp的那个版本也留着了
#include
typedef long long ll;
int n,m,i;
int a[100005];
ll BinarySearch(ll l, ll r)
{
if (l>r)
return l;
else
{
ll sum=0, cnt=0, mid=(l+r)>>1;
for (i=0; i<n; i++)
{
if ((sum+a[i])>mid)
sum=a[i], cnt++;
else
sum+=a[i];
}
if (cnt<m)
return BinarySearch(l,mid-1);
else
return BinarySearch(mid+1,r);
}
}
int main()
{
scanf("%d%d",&n,&m);
ll sum=0; int maxn=0;
for (i=0; i<n; ++i)
{
scanf("%d",&a[i]);
sum+=a[i];
maxn=(maxn>a[i])?maxn:a[i];
}
printf("%lld",BinarySearch(maxn,sum));
return 0;
}
以下为Cpp版本:
#include
#include
using namespace std;
typedef long long ll;
const ll N=1e5+5;
ll BinarySearch(ll, ll);
int n,m;
int a[N];
int main()
{
// freopen("9.in","r",stdin);
ios::sync_with_stdio(0);
cin>>n>>m;
ll sum=0; int maxn=0;
for (int i=0; i<n; ++i)
{
cin>>a[i];
sum+=a[i];
maxn=max(a[i],maxn);
}
cout<<BinarySearch(maxn,sum);
// fclose(stdin);
return 0;
}
ll BinarySearch(ll l, ll r)
{
if (l>r)
return l;
else
{
ll sum=0, cnt=0, mid=(l+r)>>1;
for (ll i=0; i<n; i++)
{
if ((sum+a[i])>mid)
sum=a[i], cnt++;
else
sum+=a[i];
}
if (cnt<m)
return BinarySearch(l,mid-1);
else
return BinarySearch(mid+1,r);
}
}
/*
input:
7 5
100
400
300
100
500
101
400
output:
500
input:
23 7
4568
8417
7598
9710
1431
9731
7755
9039
524
8998
5861
963
6882
2463
6606
6459
8391
6558
6166
6786
4263
6593
2324
output:
22410
*/
以上是机考前两组测试数据(其他的太长了),自测的同学可以试试~~
PS:大佬扒出这是NOI训练题,遂又发现题源是USACO,我查了一下POJ也有此题,不愧为二分答案的经典题!!
(然而我并没有做过Orzzzz)
一开始我打的是以下代码,但可过USACO,洛谷那道不能过
ll BinarySearch(ll l, ll r)
{
if (l==r)
return l;
else
{
ll sum=0, cnt=0, mid=(l+r)>>1;
for (ll i=0; i<n; i++)
{
if ((sum+a[i])>mid)
sum=a[i], cnt++;
else
sum+=a[i];
}
if (cnt<m)
return BinarySearch(l,mid);
else
return BinarySearch(mid+1,r);
}
}
任何尾递归也都能改成迭代写法(仅用while实现),有兴趣的同学也不妨试试