NOIP模拟7
期望得分:100+100+20=220
实际得分:100+95+20=215
T1 洛谷 P1306 斐波那契公约数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<cstring> using namespace std; typedef long long LL; LL t[2][2],ans[2][2],r[2][2]; const int mod=1e8; int gcd(int a,int b) { return !b ? a : gcd(b,a%b); } void mul(LL a[2][2],LL b[2][2]) { memset(r,0,sizeof(r)); for(int i=0;i<2;i++) for(int j=0;j<2;j++) for(int k=0;k<2;k++) r[i][j]+=a[i][k]*b[k][j],r[i][j]%=mod; for(int i=0;i<2;i++) for(int j=0;j<2;j++) a[i][j]=r[i][j]; } int main() { int a,b; scanf("%d%d",&a,&b); int p=gcd(a,b); t[0][0]=t[0][1]=t[1][0]=1;; ans[0][0]=ans[0][1]=1; if(p==2 || p==1) { printf("1"); return 0; } p-=2; while(p) { if(p&1) mul(ans,t); mul(t,t); p>>=1; } printf("%lld",ans[0][0]); }
T2 51nod 1431 快乐排队
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1431
贪心
每个点每往上一步-1,每往下一步+1
最上面肯定越大越好
假设所有的点都到最上面
按从大到小的顺序,取最大的作为第一个
然后所有的点每往下移一步就+1
所以从2开始枚举当前要放从上往下的第sum个,如果这个点+sum-1<=上一个,就放
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<algorithm> #include<iostream> #define N 200001 using namespace std; void read(int &x) { x=0; char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); } } int a[N]; int main() { int n; read(n); for(int i=1;i<=n;i++) read(a[i]); for(int i=1;i<=n;i++) a[i]=i-n+a[i]; sort(a+1,a+n+1,greater<int>()); int last,sum=0; last=a[1],sum++; for(int i=2;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,上一步可以是任何操作
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<algorithm> #define N 1000001 using namespace std; int p[5]={2,3,5,7,11}; int dp[N][2]; int dfs(int x,int y) { if(x==1) return 0; if(dp[x][y]) return dp[x][y]; dp[x][y]=N; for(int i=0;i<5;i++) if(!(x%p[i])) dp[x][y]=min(dp[x][y],dfs(x/p[i],1)+p[i]); if(!y) return dp[x][y]; // dp[x][0]=dp[x][1]; for(int i=1;i<5;i++) dp[x][y]=min(dp[x][y],dfs(x+i,0)+i); return dp[x][y]; } int main() { int n; scanf("%d",&n); printf("%d",dfs(n,1)); }