期望得分:100+100+20=220
实际得分:100+95+20=215
T1 洛谷 P1306 斐波那契公约数
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long LL;
LL t[][],ans[][],r[][];
const int mod=1e8;
int gcd(int a,int b)
{
return !b ? a : gcd(b,a%b);
}
void mul(LL a[][],LL b[][])
{
memset(r,,sizeof(r));
for(int i=;i<;i++)
for(int j=;j<;j++)
for(int k=;k<;k++)
r[i][j]+=a[i][k]*b[k][j],r[i][j]%=mod;
for(int i=;i<;i++)
for(int j=;j<;j++)
a[i][j]=r[i][j];
}
int main()
{
int a,b;
scanf("%d%d",&a,&b);
int p=gcd(a,b);
t[][]=t[][]=t[][]=;;
ans[][]=ans[][]=;
if(p== || p==) { printf(""); return ; }
p-=;
while(p)
{
if(p&) mul(ans,t);
mul(t,t); p>>=;
}
printf("%lld",ans[][]);
}
T2 51nod 1431 快乐排队
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1431
贪心
每个点每往上一步-1,每往下一步+1
最上面肯定越大越好
假设所有的点都到最上面
按从大到小的顺序,取最大的作为第一个
然后所有的点每往下移一步就+1
所以从2开始枚举当前要放从上往下的第sum个,如果这个点+sum-1<=上一个,就放
#include<cstdio>
#include<algorithm>
#include<iostream>
#define N 200001
using namespace std;
void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
}
int a[N];
int main()
{
int n;
read(n);
for(int i=;i<=n;i++) read(a[i]);
for(int i=;i<=n;i++) a[i]=i-n+a[i];
sort(a+,a+n+,greater<int>());
int last,sum=;
last=a[],sum++;
for(int i=;i<=n;i++)
if(a[i]+sum<=last) last=a[i]+sum,sum++;
if(sum==n) printf("Happy");
else printf("Sad");
}
std 做法:
a[i]+i,不变,排序去重
T3 51nod 1693 水群
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1693
x向i*x连边权为i的边
只需要连素数
经各种研究发现
在<=1e6时,退格操作最多有4个,且只会用到前5个素数
所以dp[i][0]表示 当前长度为i,上一步操作为退格
dp[i][1]表示当前长度为i,上一步可以是任何操作
#include<cstdio>
#include<algorithm>
#define N 1000001
using namespace std;
int p[]={,,,,};
int dp[N][];
int dfs(int x,int y)
{
if(x==) return ;
if(dp[x][y]) return dp[x][y];
dp[x][y]=N;
for(int i=;i<;i++)
if(!(x%p[i])) dp[x][y]=min(dp[x][y],dfs(x/p[i],)+p[i]);
if(!y) return dp[x][y];
// dp[x][0]=dp[x][1];
for(int i=;i<;i++) dp[x][y]=min(dp[x][y],dfs(x+i,)+i);
return dp[x][y];
}
int main()
{
int n;
scanf("%d",&n);
printf("%d",dfs(n,));
}