A.【NOIP2012 提高组 day1】Vigenère密码
思路:按照题目思路进行模拟
观察图后,可以发现规律
m=c-(k-'a');
这时若m<'a' 则 m='z'-('a'-m-1);
然后将答案输出即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 string k; 5 char m,c; 6 int x=0,l; 7 8 bool small(char s){ 9 if(s>='a'&&s<='z') return 1; 10 return 0; 11 } 12 13 bool big(char s){ 14 if(s>='A'&&s<='Z') return 1; 15 return 0; 16 } 17 18 int main(){ 19 cin>>k; 20 l=k.size(); 21 getchar(); 22 while(scanf("%c",&c)){ 23 if(!small(c) && !big(c)) break; 24 if(small(k[x])) m=c-(k[x]-'a'); 25 else if(big(k[x])) m=c-(k[x]-'A'); 26 if(small(c) && m<'a') m='z'-('a'-m-1); 27 else if(big(c) && m<'A') m='Z'-('A'-m-1); 28 x++; 29 if(x>=l) x=0; 30 printf("%c",m); 31 } 32 return 0; 33 }
B. 【NOIP2012 提高组 day1】国王游戏
思路:这是一道贪心题
贪心策略是将a*b的小的放在前面。
证明可使用微扰法:
先假设p1在前p2在后
所以ans1=max( a0/b1,a0*a1/b2)
然后将p1p2互换
ans2=max(a0/b2,a0*a2/b1)
我们设k1=a0/b1,k2=a0*a1/b2,k3=a0/b2,k4=a0*a2/b1
显然有 k4>k1,k2>k3
若ans1<ans2
则 k4>k2
即:a2/b1>a1/b2
a1*b1<a2*b2
也就是只要满足这个条件,就是最优情况
这道题需要用到高精度
1 #include <bits/stdc++.h> 2 using namespace std; 3 int now[20010],sum[20010],ans[20010],add[20010]; 4 struct Node { 5 int a; 6 int b; 7 long long a_b; 8 }node[1010]; 9 inline int read(){ 10 int x=0,f=1; 11 char s=getchar(); 12 while(!isdigit(s)){ 13 f*=(s=='-')? -1:1; 14 s=getchar(); 15 } 16 do x=x*10+(s^48),s=getchar(); 17 while(isdigit(s)); 18 return x*f; 19 } 20 void times(int x) { 21 memset(add,0,sizeof(add)); 22 for(int i=1;i<=ans[0];i++) { 23 ans[i]=ans[i]*x; 24 add[i+1]+=ans[i]/10; 25 ans[i]%=10; 26 } 27 for(int i=1;i<=ans[0]+4;i++) { 28 ans[i]+=add[i]; 29 if(ans[i]>=10) { 30 ans[i+1]+=ans[i]/10; 31 ans[i]%=10; 32 } 33 if(ans[i]!=0) { 34 ans[0]=max(ans[0],i); 35 } 36 } 37 return ; 38 } 39 int divite(int x) { 40 memset(add,0,sizeof(add)); 41 int q=0; 42 for(int i=ans[0];i>=1;i--) { 43 q*=10; 44 q+=ans[i]; 45 add[i]=q/x; 46 if(add[0]==0 && add[i]!=0) { 47 add[0]=i; 48 } 49 q%=x; 50 } 51 return 0; 52 } 53 bool compare() { 54 if(sum[0]==add[0]) { 55 for(int i=add[0];i>=1;i--) { 56 if(add[i]>sum[i]) return 1; 57 if(add[i]<sum[i]) return 0; 58 } 59 } 60 if(add[0]>sum[0]) return 1; 61 if(add[0]<sum[0]) return 0; 62 } 63 void zh () { 64 memset(sum,0,sizeof(sum)); 65 for(int i=add[0];i>=0;i--) { 66 sum[i]=add[i]; 67 } 68 return ; 69 } 70 bool cmp(Node a,Node b) { 71 return a.a_b<b.a_b; 72 } 73 int main() { 74 int n=read(); 75 for(int i=0;i<=n;i++) { 76 node[i].a=read(),node[i].b=read(); 77 node[i].a_b=node[i].a*node[i].b; 78 } 79 sort(node+1,node+n+1,cmp); 80 ans[0]=1,ans[1]=1; 81 for(int i=1;i<=n;i++) { 82 times(node[i-1].a); 83 divite(node[i].b); 84 if(compare()) { 85 zh(); 86 } 87 } 88 for(int i=sum[0];i>=1;i--) 89 printf("%d",sum[i]); 90 return 0; 91 }
C. 【NOIP2012 提高组 day1】开车旅行
设f[i][j]为在位置i走2^j轮的位置,一轮就是A走和B走一次,fa[i][j]就是A在位置i走2^j轮的距离,fb[i][j]类同。
另外:从每个点到下一个用倍增来优化
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #include <cstring> 5 #include <set> 6 7 using namespace std; 8 9 const int maxn = 100005; 10 int n, x0, m, k,x1, na[maxn], nb[maxn],ans; 11 long long ansa = 1e5,ansb = 0ll,fa[maxn][20], fb[maxn][20], f[maxn][20]; 12 13 struct node 14 { 15 int id, high; 16 bool operator < (const node & b) const { 17 return high < b.high; 18 } 19 }c[maxn]; 20 21 struct node2 22 { 23 int id, gaoducha; 24 bool operator < (const node2 & b) const { 25 if (gaoducha != b.gaoducha) 26 return gaoducha < b.gaoducha; 27 else 28 return c[id].high < c[b.id].high; 29 } 30 }temp[5]; 31 32 set <node> s; 33 34 void init(int i) 35 { 36 set <node> ::iterator it = s.find(c[i]); 37 int j = 0; 38 if (it != s.begin()) 39 { 40 --it; 41 temp[++j] = (node2) { it->id, abs(it->high - c[i].high) }; 42 if (it != s.begin()) 43 { 44 --it; 45 temp[++j] = (node2) { it->id, abs(it->high - c[i].high) }; 46 ++it; 47 } 48 ++it; 49 } 50 if ((++it) != s.end()) 51 { 52 temp[++j] = (node2) { it->id, abs(it->high - c[i].high) }; 53 if ((++it) != s.end()) 54 temp[++j] = (node2) { it->id, abs(it->high - c[i].high) }; 55 } 56 sort(temp + 1, temp + j + 1); 57 nb[i] = temp[1].id; 58 if (j == 1) 59 return; 60 na[i] = temp[2].id; 61 return; 62 } 63 64 void query(int st, int x, long long &ta, long long &tb) 65 { 66 for (int i = 19; i >= 0; i--) 67 if (f[st][i] && fa[st][i] + fb[st][i] <= x) 68 { 69 ta += fa[st][i]; 70 tb += fb[st][i]; 71 x -= fa[st][i] + fb[st][i]; 72 st = f[st][i]; 73 } 74 if (!na[st]) 75 return; 76 int tempans = abs(c[na[st]].high - c[st].high); 77 if (tempans <= x) 78 ta += tempans; 79 } 80 81 int main() 82 { 83 scanf("%d", &n); 84 for (int i = 1; i <= n; i++) 85 { 86 scanf("%d", &c[i].high); 87 c[i].id = i; 88 } 89 for (int i = n; i;i--) 90 { 91 s.insert(c[i]); 92 if (i != n) 93 init(i); 94 } 95 for (int i = 1; i <= n; i++) 96 { 97 int p1 = na[i], p2 = nb[na[i]]; 98 fa[i][0] = p1 ? abs(c[p1].high - c[i].high) : 0; 99 fb[i][0] = p2 ? abs(c[p2].high - c[p1].high) : 0; 100 f[i][0] = p2; 101 } 102 for (int j = 1; j < 20;j++) 103 for (int i = 1; i <= n; i++) 104 { 105 f[i][j] = f[f[i][j - 1]][j - 1]; 106 fa[i][j] = fa[i][j - 1] + fa[f[i][j - 1]][j - 1]; 107 fb[i][j] = fb[i][j - 1] + fb[f[i][j - 1]][j - 1]; 108 } 109 scanf("%d", &x0); 110 ans = 0; 111 for (int i = 1; i <= n; i++) 112 { 113 long long ta = 0ll, tb = 0ll; 114 query(i, x0, ta, tb); 115 if (tb && (!ans || ansa * tb > ansb * ta)) 116 { 117 ansa = ta; 118 ansb = tb; 119 ans = i; 120 } 121 } 122 printf("%d ", ans); 123 scanf("%d", &m); 124 while (m--) 125 { 126 scanf("%d%d", &k, &x1); 127 long long ta = 0ll, tb = 0ll; 128 query(k, x1, ta, tb); 129 printf("%d %d ", ta, tb); 130 } 131 return 0; 132 }