1.Vigenère密码
一开始以为是明码反暗码,就直接把密码表预处理,然后测了多好多遍还是没过样例,十分困惑与不解然后就看一了一遍题目(咳,
暗码减去密码取模
这一遍很自信然后爆零了
(输出区分大小写
#include
#include
#include
#include
using namespace std;
const int maxn=1010;
char m[maxn],k[maxn];
int lm,lk,key[maxn];
int main()
{
freopen("vigenere.in","r",stdin);
freopen("vigenere.out","w",stdout);
scanf("%s%s",k,m);
lm=strlen(m),lk=strlen(k);
for(int i=0;i='a'&&k[i]<='z') key[i]=k[i]-'a';
else key[i]=k[i]-'A';
int j=0;
for(int i=0;i='a'&&m[i]<='z') tmp='a',m[i]-='a';
else tmp='A',m[i]-='A';
m[i]-=key[j];
if(m[i]<0) m[i]+=26;
m[i]+=tmp;
j++;
if(j>=lk) j-=lk;
}
for(int i=0;i
2.国王游戏
手推几组数据就很容易得到一个结论:最优的方案肯定是大臣们按成绩升序排序时候的序列,然后要打高精度(想吐。初测六十,位数最高点没处理好
结论摸鱼证明:
A1…Ax-1AxAx+1…Ay-1AyAy+1
设A1到Ax-1乘积为k1,那么Ax的钱就是k1/Bx,
设Ax+1到Ay-1乘积为k2,那么Ay的钱就是k1*Ax*k2/By
那么最优方案就是max(k1/Bx,k1*Ax*k2/By)
讲Ay和Ax互换,同理可得此时最优方案是max(k1/By,k1*k2*Ay/Bx)
易得
k1*Ax*k2/By>k1/By
k1*k2*Ay/Bx>k1/Bx
则
比较k1*Ax*k2/By k1*k2*Ay/Ax
很容易可以判断 大的放后面最优值就最小
#include
#include
#include
#include
#define ll long long
using namespace std;
struct ppl{
ll a,b;
} p[1005];
ll n,x;
ll sum[5000],ans[5000],divn[5000];
bool cmp(ppl x,ppl y){
return x.a*x.b0;k--){
if(ans[k]>divn[k])return;
if(ans[k]0){
sum[0]++;
sum[sum[0]]=x;
}
x=0;
memset(divn,0,sizeof(divn));
for(ll j=sum[0];j>0;j--){
divn[j]=(x*10000+sum[j])/p[i].b;
x=(x*10000+sum[j])%p[i].b;
}
divn[0]=sum[0];
while(divn[divn[0]]==0)divn[0]--;
compare();
}
printf("%lld",ans[ans[0]]);
for(ll i=ans[0]-1;i>0;i--){
printf("%lld",ans[i]/1000);
printf("%lld",ans[i]/100%10);
printf("%lld",ans[i]/10%10);
printf("%lld",ans[i]%10);
}
return 0;
}
3.开车旅行
因为第二题的高精度所以得分 0
可以直接模拟距离每个点最近和次近的点 打得好70
也可以用双向链表模拟 这个很快 但是很容易出错 100
线段树:
线段树维护三个值,区间内最小值、最大值、数的个数。从右往左找(nn~11),当找到第ii个点时,第i+1i+1个点到第nn个点的高度值已经更新过了线段树。通过线段树找出高度比HiHi大的最小、次小值,以及找出高度比HiHi小的最大、次大值,便可以更新第ii个点的最近、次近的点的编号了。因为HiHi的值可能很大,会空间超限,所以做之前需要离散化一次
答案会很大,需要开int64(long long)
然后第二个小问就用倍增
设f[i][j][0]表示从城市i出发,小A经过2^j轮(注意是轮)之后走的路程。
f[i][j][1]表示小B走的路程
g[i][j]表示走到那个城市。
#include
#include
#include
#include
基础还是不踏实