P1786 帮贡排序
题目背景
帮派名号:星月家园
帮主尊号:Dragonfly Kang
帮派 ID:2685023
帮派等级:4
帮派人数:101/110
帮派技能:(?)
"星月家园"资料,欢迎各位豆友加入 ^_^
在 absi2011 的帮派里,死号偏多。现在 absi2011 和帮主等人联合决定,要清除一些死号,加进一些新号,同时还要鼓励帮贡多的人,对帮派进行一番休整。
题目描述
目前帮派内共最多有:
- 1 位帮主(BangZhu)
- 2 位副帮主(FuBangZhu)
- 2 位护法(HuFa)
- 4 位长老(ZhangLao)
- 7 位堂主(TangZhu)
- 25 名精英(JingYing)
- 若干(数量不限)帮众(BangZhong)
保证以上职位是从高到低排列的。
现在 absi2011 要对帮派内几乎所有人的职位全部调整一番。他发现这是个很难的事情。于是要求你帮他调整。
他给你每个人的以下数据:
- 名字
- 原来职位
- 帮贡
- 等级
他要按照以下关键字给帮派内的人(帮主、副帮主除外)按以下关键字排序:
- 帮贡(从高到低)第一关键字
- 在输入中出现的顺序(从前到后)第二关键字
然后更新这些人的职位:
- 第 1∼2 名:护法
- 第 3∼6 名:长老
- 第 7∼13 名:堂主
- 第 14∼38 名:精英
- 第 39∼(n−3) 名:帮众
可是,乐斗的显示并不按帮贡排序而按职位和等级排序。
他要你按照以下关键字排序并求出最后乐斗显示的列表(在他调整过职位后):
- 职位(从高到低)第一关键字
- 等级(从高到低)第二关键字
- 在输入中出现的顺序(从前到后)第三关键字
注意:absi2011 无权调整帮主、副帮主的职位,包括他自己的。
输入格式
第一行一个正整数 n,表示星月家园内帮友的人数。
下面 n 行每行两个字符串两个整数,表示每个人的名字、职位、帮贡、等级。
输出格式
一共输出 n 行,每行包括排序后乐斗显示的名字、职位、等级。
输入输出样例
输入 #1复制
9
DrangonflyKang BangZhu 100000 66
RenZaiJiangHu FuBangZhu 80000 60
absi2011 FuBangZhu 90000 60
BingQiLingDeYanLei HuFa 89000 58
Lcey HuFa 30000 49
BangYou3 ZhangLao 1000 1
BangYou1 TangZhu 100 40
BangYou2 JingYing 40000 10
BangYou4 BangZhong 400 1
输出 #1复制
DrangonflyKang BangZhu 66
RenZaiJiangHu FuBangZhu 60
absi2011 FuBangZhu 60
BingQiLingDeYanLei HuFa 58
BangYou2 HuFa 10
Lcey ZhangLao 49
BangYou1 ZhangLao 40
BangYou3 ZhangLao 1
BangYou4 ZhangLao 1
说明/提示
对于 10% 的数据,保证 n=3。
对于 40% 的数据,保证各个人的帮贡均为 0。
对于 100% 的数据,保证:
- 3≤n≤110
- 1≤ 名字长度 ≤30
- 所有名字两两不同
- 名字只包含 ASCII 可见字符
- 0≤ 各个人的帮贡 ≤109
- 1≤ 各个人等级 ≤150
- 职位必定为以下七个中的一个:
- BangZhu
- FuBangZhu
- HuFa
- ZhangLao
- TangZhu
- JingYing
- BangZhong
- 初始时帮派内最多有:
- 1 位帮主
- 2 位副帮主
- 2 位护法
- 4 位长老
- 7 位堂主
- 25 名精英
- 恰好有一名帮主
- 恰好有两名副帮主
- 恰好有一名副帮主叫 absi2011
【题目来源】
absi2011 授权题目
实现代码:
cpp
#include<bits/stdc++.h>
using namespace std;
int n;
struct node{
string na,zw,xzw;
long long bg;
int le,h;
}ab[115];
int change(string a){
if (a=="BangZhu") return 0;
if (a=="FuBangZhu") return 1;
if (a=="HuFa") return 2;
if (a=="ZhangLao") return 3;
if (a=="TangZhu") return 4;
if (a=="JingYing") return 5;
if (a=="BangZhong") return 6;
}
int cmp1(node x,node y){
if (x.bg==y.bg) return x.h<y.h;
else return x.bg>y.bg;
}
int cmp2(node x,node y){
if (change(x.xzw)==change(y.xzw)){
if (x.le==y.le) return x.h<y.h;
return x.le>y.le;
}
return change(x.xzw)<change(y.xzw);
}
int main(){
cin>>n;
for (int i=1;i<=n;i++){
cin>>ab[i].na>>ab[i].zw>>ab[i].bg>>ab[i].le;
ab[i].h=i;
}
sort(ab+4,ab+1+n,cmp1);
for (int i=1;i<=n;i++){
if (i==1) ab[i].xzw="BangZhu";
else if (i==2||i==3) ab[i].xzw="FuBangZhu";
else if (i==4||i==5) ab[i].xzw="HuFa";
else if (i>=6&&i<=9) ab[i].xzw="ZhangLao";
else if (i>=10&&i<=16) ab[i].xzw="TangZhu";
else if (i>=17&&i<=41) ab[i].xzw="JingYing";
else ab[i].xzw="BangZhong";
}
sort(ab+1,ab+1+n,cmp2);
for (int i=1;i<=n;i++){
cout<<ab[i].na<<" "<<ab[i].xzw<<" "<<ab[i].le<<endl;
}
return 0;
}
P1591 阶乘数码
题目描述
求 n! 中某个数码出现的次数。
输入格式
第一行为 t(t≤10),表示数据组数。接下来 t 行,每行一个正整数 n(n≤1000) 和数码 a。
输出格式
对于每组数据,输出一个整数,表示 n! 中 a 出现的次数。
输入输出样例
输入 #1复制
2
5 2
7 0
输出 #1复制
1
2
实现代码:
cpp
#include<bits/stdc++.h>
using namespace std;
long long t,a[10009];
int main(){
cin>>t;
for(int i=1;i<=t;i++)
{
long long n,k,ws=1,ans=0;
cin>>n>>k;
a[1]=1;
for(int j=2;j<=10000;j++)a[j]=0;
for(int j=2;j<=n;j++)
{
for(int l=1;l<=ws;l++)
{
a[l]*=j;
}
for(int l=1;;l++)
{
a[l+1]+=a[l]/10;
a[l]%=10;
if(l>=ws&&a[l+1]==0){ws=l;break;}
}
}
for(int j=1;j<=ws;j++)
{
if(a[j]==k)ans++;
}
cout<<ans<<endl;
}
}
P1249 最大乘积
题目描述
一个正整数一般可以分为几个互不相同的自然数的和,如 3=1+2,4=1+3,5=1+4=2+3,6=1+5=2+4。
现在你的任务是将指定的正整数 n 分解成若干个互不相同的自然数(也可以不分解,就是这个数字本身)的和,且使这些自然数的乘积最大。
输入格式
只有一个正整数 n,(3≤n≤10000)。
输出格式
第一行是分解方案,相邻的数之间用一个空格分开,并且按由小到大的顺序。
第二行是最大的乘积。
输入输出样例
输入 #1复制
10
输出 #1复制
2 3 5
30
实现代码:
cpp
#include<iostream>
using namespace std;
int a[10001]={};
int s[10001]={};
int n,len=1;
void mul(int x)
{
for(int i=1;i<=len;i++)s[i]*=x;
for(int i=1;i<=len;i++)
{
s[i+1]+=s[i]/10;
s[i]%=10;
}
while(s[len+1]>0)
{
len++;
s[len+1]+=s[len]/10;
s[len]%=10;
}
}
int main()
{
cin>>n;
if(n==3)
{
cout<<3<<endl;
cout<<3<<endl;
return 0;
}
if(n==4)
{
cout<<4<<endl;
cout<<4<<endl;
return 0;
}
s[0]=s[1]=1;
int Sum=0,tot=0;
for(int i=2;Sum<n;Sum+=i,i++)a[++tot]=i;
if(Sum>n+1)a[Sum-n-1]=0;
else if(Sum==n+1)a[tot]++,a[1]=0;
for(int i=1;i<=tot;i++)
{
if(a[i])
{
cout<<a[i]<<' ';
mul(a[i]);
}
}
cout<<endl;
for(int i=len;i>=1;i--)
cout<<s[i];
cout<<endl;
return 0;
}
P1045 [NOIP 2003 普及组] 麦森数
题目描述
形如 2P−1 的素数称为麦森数,这时 P 一定也是个素数。但反过来不一定,即如果 P 是个素数,2P−1 不一定也是素数。到 1998 年底,人们已找到了 37 个麦森数。最大的一个是 P=3021377,它有 909526 位。麦森数有许多重要应用,它与完全数密切相关。
任务:输入 P(1000<P<3100000),计算 2P−1 的位数和最后 500 位数字(用十进制高精度数表示)
输入格式
文件中只包含一个整数 P(1000<P<3100000)
输出格式
第一行:十进制高精度数 2P−1 的位数。
第 2∼11 行:十进制高精度数 2P−1 的最后 500 位数字。(每行输出 50 位,共输出 10 行,不足 500 位时高位补 0)
不必验证 2P−1 与 P 是否为素数。
输入输出样例
输入 #1复制
1279
输出 #1复制
386
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
00000000000000104079321946643990819252403273640855
38615262247266704805319112350403608059673360298012
23944173232418484242161395428100779138356624832346
49081399066056773207629241295093892203457731833496
61583550472959420547689811211693677147548478866962
50138443826029173234888531116082853841658502825560
46662248318909188018470682222031405210266984354887
32958028878050869736186900714720710555703168729087
说明/提示
【题目来源】
NOIP 2003 普及组第四题
实现代码:
cpp
#include<bits/stdc++.h>
int n,a[1010],res[1010],cnt;
void multiply1(){
int tmp[1010]={0};
for(int i=0;i<500;i++){
for(int j=0;j<500;j++) tmp[i+j]+=res[i]*a[j];
}
int t=0;
for(int i=0;i<500;i++){
tmp[i]+=t;
res[i]=tmp[i]%10;
t=tmp[i]/10;
}
}
void multiply2(){
int tmp[1010]={0};
for(int i=0;i<500;i++){
for(int j=0;j<500;j++) tmp[i+j]+=a[i]*a[j];
}
int t=0;
for(int i=0;i<500;i++){
tmp[i]+=t;
a[i]=tmp[i]%10;
t=tmp[i]/10;
}
}
void quick_pow(int p){
res[0]=1,a[0]=2;
while(p){
if(p&1) multiply1();
multiply2();
p>>=1;
}
}
int main(){
scanf("%d",&n);
int length=n*log10(2)+1;
printf("%d\n",length);
quick_pow(n);
res[0]-=1;
for(int i=499;i>=0;i--){
if(cnt==50) printf("\n"),cnt=0;
printf("%d",res[i]);
cnt++;
}
return 0;
}