在数轴上你从0点出发,要到达m点,只能通过传送点移动,传送点给你一对a,b,a代表传送点的位置,b代表最远可以传送的长度。问你能不能到m点。
首先因为只能通过传送点移动,0点必须有传送点,然后为了能到达m点,0点到m点之间必须被传送段完全覆盖,至于实现,只要维护一个目前能达到的最远距离就好。
#include<iostream> using namespace std; int main(){ int n,m,a,b,r=0,flag=0; scanf("%d%d",&n,&m); for(int i=0;i<n;i++){ scanf("%d%d",&a,&b); if(a==0)flag=1; if(a<=r)r=r>b?r:b; } if(r<m)flag=0; printf("%s\n",flag?"YES":"NO"); return 0; }
给你颗树,每一次可以选择一个子树全染成一种颜色,问你要染成要求的颜色最少要多少步。
因为染子树,所以上面染完必然会覆盖下面的,从根到叶dfs遍历,父节点和子节点要求颜色不同的最终答案就加1,根节点要染一次所以额外还要加一次,我下面的写法是用了一个假父节点0来方便的处理这个问题的。
#include<iostream> #include<algorithm> #include<vector> using namespace std; vector<int> e[100005]; int v[100005]; int ans; void dfs(int x, int f) { for (auto i : e[x]) { if (i != f) { if (v[i] != v[x])ans++; dfs(i, x); } } } int main() { int n, x; scanf("%d", &n); for (int i = 2; i <= n; i++) { scanf("%d", &x); e[i].emplace_back(x); e[x].emplace_back(i); } for (int i = 1; i <= n; i++) { scanf("%d", &x); v[i] = x; } ans++; dfs(1, 0); printf("%d\n", ans); return 0; }
给出一颗n层的树。以及从第0层开始给出每层的节点个数。求是否存在同构,若存在输出“ambiguous”和 2 个可以同构的树,如果不可以输出“perfect”。
很容易知道,只要相邻的两层节点数都大于1就一定有同构。
#include<iostream> using namespace std; int s[100005]; int p[200005]; int main(){ int n; scanf("%d",&n); int flag=0; for(int i=0;i<=n;i++){ scanf("%d",s+i); if(i&&s[i]>1&&s[i-1]>1) { flag=i; } } if(!flag){ printf("perfect\n"); scanf(" "); return 0; } int f=0; for(int i=0;i<=n;i++){ int x=f; while(f-x<s[i])p[f++]=x; if(i&&s[i]>1&&s[i-1]>1) { flag=f-1; } } printf("ambiguous\n"); for(int i=0;i<f;i++) printf("%d ",p[i]); printf("\n"); for(int i=0;i<f;i++){ if(i==flag)p[i]--; printf("%d ",p[i]); } printf("\n"); scanf(" "); return 0; }
\(T\)次询问,每次问有没有两个非负整数\(x,y\)使得\(3*x + 7*y = n\)。
数据很小怎么做都行。
//方法二 #include<iostream> using namespace std; int dp[200]; int main() { int n, x; dp[0] = 1; for (int i = 3; i <= 100; i++) dp[i] = dp[i - 3] ? 1 : dp[i]; for (int i = 7; i <= 100; i++) dp[i] = dp[i - 7] ? 1 : dp[i]; scanf("%d", &n); while (n--) { scanf("%d", &x); printf("%s\n", dp[x] ? "YES" : "NO"); } }
//方法三 #include<iostream> using namespace std; int ans[105]={1,1,1,0,1,1,0,0,1,0,0,1}; int main() { int n,x; scanf("%d", &n); while (n--) { scanf("%d", &x); printf("%s\n",!ans[x] ? "YES" : "NO"); } }
一个人在打怪,他每回合可以选择喝药加血或者打怪,然后怪物会攻击他一次,让你输出一个他可以打死怪物的方案(任意一个即可,特殊判定),但是注意他的血量可以无上限。第一行输入他的当前血量h1,攻击力a1,药每次回复c的血量,第二行输入怪物的血量h2,怪物的攻击力a2,。
由于你回血量一定高于攻击力,所以,一直打怪,如果下一次要被杀死了,再回血就好,当然先把血回到可以杀死怪物的状态也行,那样可能还会更快点,但反正数据范围很小,随便做。
#include<iostream> using namespace std; int p[10500]; int main() { int h1, h2, a1, a2, c,k=0; scanf("%d%d%d%d%d", &h1,&a1,&c,&h2,&a2); while (h2 > 0) { if (h2 - a1 <= 0) { p[k] = 1; h2 -= a1; } else if (h1 - a2 > 0) { p[k] = 1; h2 -= a1; } else h1 += c; k++; h1 -= a2; } printf("%d\n", k); for (int i = 0; i < k; i++) { printf("%s\n", p[i] ? "STRIKE" : "HEAL"); } }
#include<iostream> using namespace std; int main() { int h1, h2, a1, a2, c1; scanf("%d%d%d", &h1, &a1, &c1); scanf("%d%d", &h2, &a2); int n = (h2 + a1 - 1) / a1;//需要攻击几次 int h = (n-1) * a2+1; //需要多少血 int m = (h - h1 + (c1 - a2 - 1)) / (c1 - a2);//需要回几次血 if (m < 0)m = 0; printf("%d\n", n + m); for (int i = 0; i < m; i++) printf("HEAL\n"); for (int i = 0; i < n; i++) printf("STRIKE\n"); }
给你n个盒子,把小盒子放进大的盒子里,这样只能看到大盒子,输出最小能够有看到的盒子数。
贪心,可以看成小的盒子替换大的盒子,因为如果大盒子套个小的,那那个大盒子能继续套的只能是比那个小盒子还小的盒子了。排序后找第一个比自己小的嵌套。
#include<iostream> #include<algorithm> using namespace std; int s[5005]; int main(){ int n; while(~scanf("%d",&n)){ for(int i=0;i<n;i++) scanf("%d",s+i); sort(s,s+n); int j=n-1; for(int i=j-1;i>=0;i--) if(s[i]<s[j]) j--; printf("%d\n",j+1); } scanf(" "); return 0; }
直接输出结果就好,数据范围很小,又是直接输入结果的题,所以实际上连素数筛都不用,暴力,哪怕是最差的\(O(n^2)\)复杂度的暴力都能过,就是要挂机跑一会。我下面是一个优化的暴力,复杂度为\(O(n\sqrt{n})\),筛法我就不写了,大家应该都会吧,欧拉筛和埃式筛都行。
(\(O(n^2)\)复杂度的暴力我电脑跑十几秒也出了)
#include<iostream> using namespace std; int main() { // int ans = 0; // for (int i = 2; i <= 100000; i++) { // int flag = 1; // for (int j = 2; j*j <= i; j++) { // if (i%j == 0) { // flag = 0; // } // } // if (flag) { // int x = i; // while (x) { // if (x % 10 == 5) { // ans++; // break; // } // x /= 10; // } // } // } // printf("%d\n", ans); printf("3282"); }
求\(A^B\)的约数和对9901取余的结果。
使用约数和定理求值,具体实现用递归二分求,求值的时候有大指数,使用快速幂解决。
#include<iostream> #include<algorithm> using namespace std; typedef long long ll; ll p[100005], c[100005]; ll pow(ll x, ll y,ll mod) { ll ans = 1%mod; while (y) { if (y & 1)ans = (ans*x) % mod; x = (x*x) % mod; y >>= 1; } return ans; } int k[105]; ll sum(ll p, ll c,ll mod) { if (c == 0)return 1; if (c == 1)return (1 + p) % mod; if (c % 2)return ((1 + pow(p, (c + 1) / 2, mod))*sum(p, (c - 1) / 2,mod))%mod; else return ((1 + pow(p, c / 2,mod))*sum(p, c / 2 - 1,mod) + pow(p, c,mod)) % mod; } int main() { ll a, b; ll mod = 9901; scanf("%lld%lld", &a, &b); int m=0; for (int i = 2; i*i <= a; i++) { if (a%i == 0) { p[m] = i; c[m] = 0; while (a%i == 0) { a /= i; c[m]++; } m++; } } if (a != 1) { p[m] = a; c[m++] = 1; } ll ans = 1; for (int i = 0; i < m; i++) { ans = (ans*sum(p[i], c[i] * b,mod)) % mod; } printf("%lld\n", ans); }