https://ac.nowcoder.com/acm/contest/3003#question
前言:嘤嘤嘤
啊,今天这次的感觉不爽,莫得手感,啊,那道dp的题我没做出来,太菜了。
A、做游戏
这个题水的太厉害了,没啥可说的。
import java.util.*;class q {q() {Scanner scanner=new Scanner(System.in);long a=scanner.nextLong();long b=scanner.nextLong();long c=scanner.nextLong();long x=scanner.nextLong();long y=scanner.nextLong();long z=scanner.nextLong();if(a>y)a=y;if(b>z)b=z;if(c>x)c=x;System.out.println(a+b+c);}}public class Main {public static void main(String[] args) {new q();}}
B、排数字
还是水题
import java.util.*;class q {q() {Scanner scanner=new Scanner(System.in);long a=scanner.nextLong();char[] b=scanner.next().toCharArray();int x=0,y=0;for(int i=0;i<a;i++){if(b[i]=='6')x++;if(b[i]=='1')y++;}System.out.println(y<x?y:x-1);}}public class Main {public static void main(String[] args) {new q();}}
C、算概率
这个题有点意思,先看看题干
牛牛刚刚考完了期末,尽管 牛牛 做答了所有
道题目,但他不知道有多少题是正确的。 不过,牛牛 知道第
道题的正确率是
。 牛牛 想知道这
题里恰好有
题正确的概率分别是多少,对
取模。 对
取模的含义是:对于一个
的不可约分数
,存在
使得
,
即为
对
取模的结果。
啊,这都什么东西,如果照这个题干的意思我完全可以一上来就假定,然后之后的就是找
,但这想法肯定不对(蜜汁自信),然后就没的想法了,刚才看了看题解,居然是动态规划。强,第一次知道状态转移方程可以这么用。
先贴出来状态转移方程
其中,表示前
道题做对
道的概率
太强了。计算的原理知道了,那么那个概率 到底是咋来的,这个题干是个嘛意思。
先贴个已经过了的代码,然后直接在里头加注释吧。
#include <bits/stdc++.h>using namespace std;const int N = 2005, mod = 1e9 + 7;//初始化long long n, p[N], f[N][N];int main() {cin >> n;//导数据for (int i = 1; i <= n; ++i)cin >> p[i];//开始动规for (int i = f[0][0] = 1; i <= n; ++i) {//每组代表队有几道题,每列代表对几道题//每组第一个数据特殊处理f[i][0] = f[i - 1][0] * (mod + 1 - p[i]) % mod;//开始状态转移for (int j = 1; j <= i; ++j)f[i][j] = (f[i - 1][j] * (mod + 1 - p[i]) + f[i - 1][j - 1] * p[i]) % mod;}//结果输出for (int i = 0; i <= n; ++i)cout << f[n][i] << ' ';return 0;}
流程是这么个流程,这个 在式子中的表现为
,迷的不行,啊,多想想,到底是为什么使他在这里呈现等价的性质。
D、数三角
这个题说白了就是判断是不是钝角三角形,直接全部列举一遍,先求出三条边的长度(其中
为最长边)然后通过
且
来判断这个三角形是否为钝角三角形。
import java.util.*;class q {//求边长的平方(避免开根后失去精度)int length(int x1,int y1,int x2,int y2){return (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);}q() {Scanner scanner=new Scanner(System.in);int a=scanner.nextInt();if(a<3){System.out.println(0);}else {int[][] l=new int[a][2];for(int i=0;i<a;i++){l[i][0]=scanner.nextInt();l[i][1]=scanner.nextInt();}int t=a-2;int y=a-1;int k=0;for(int z=0;z<t;z++){for(int x=z+1;x<y;x++){for(int c=x+1;c<a;c++){double l1=length(l[z][0],l[z][1],l[x][0],l[x][1]);double l2=length(l[x][0],l[x][1],l[c][0],l[c][1]);double l3=length(l[c][0],l[c][1],l[z][0],l[z][1]);double[] p={l1,l2,l3};Arrays.sort(p);if(p[0]+p[1]<p[2]&&2*Math.sqrt(p[0]*p[1])+p[0]+p[1]>p[2])k++;}}}System.out.println(k);}}}public class Main {public static void main(String[] args) {new q();}}
E、做计数
emmmmm,这个题倒是不难,就是会有人一见陷入一种思维盲区,即认为
和
都是平方数,但,你们忘了可爱的
,实际上,我们可以把
理解为
。
所以只需令为平方数即可。而
;所以只要枚举小于
的平方数就可以了。
import java.util.*;class q {q() {Scanner scanner=new Scanner(System.in);int n=scanner.nextInt();long k=0;long s=0;long sum=0;for(int z=1;(k=z*z)<=n;z++){int i;s=0;for(i=1;i*i<=k;i++){if(k%i==0)s++;}s*=2;s--;sum+=s;}System.out.println(sum);}}public class Main {public static void main(String[] args) {new q();}}
F、拿物品
这个题……怎么说,刚一到手你可能被花花题干迷惑了双眼,然后在和
中迷惑了双眼,不知道先考虑
还是
。我们可以把每一个点统一出一个贡献标准来。你如果选了一个点,那对方就选不了这个点,所以这个点对你本人的贡献为你可以获得的点数和对方获得不了的点数的和
。那么标准确定了,然后就是个排序,然后挨个选当前可以取到的最大值就可以了。
import java.util.*;class q {//快速排序private void quickSort(long[] a, int l, int r, int[] m){if(l>=r)return;int i = l; int j = r; long key = a[m[l]],p=m[l];while(i<j){while(i<j && a[m[j]]>=key)j--;if(i<j){m[i] = m[j];i++;}while(i<j && a[m[i]]<key)i++;if(i<j){m[j] = m[i];j--;}}m[i] = (int) p;quickSort(a, l, i-1,m);quickSort(a, i+1, r,m);}q() {Scanner scanner=new Scanner(System.in);int n=scanner.nextInt();long[] k=new long[n];int[] m=new int[n];for(int i=0;i<n;i++){k[i]=scanner.nextInt();m[i]=i;}for(int i=0;i<n;i++){k[i]+=scanner.nextInt();}quickSort(k,0,n-1,m);for(int i=n-1;i>=0;i-=2) {System.out.print(m[i]+1);System.out.print(' ');}System.out.println();for(int i=n-2;i>=0;i-=2) {System.out.print(m[i]+1);System.out.print(' ');}}}public class Main {public static void main(String[] args) {new q();}}
G、判正误
先来看看这丑陋的题干在问的是哪个的式子
多么丑陋。
首先的想法是同余,然后看是不是一样,然后当时我的代码不知道出了什么故障,说我tle。我还以为要进行优化,就又把别的又调试了调试,还是不行。于是我推到了全重写了一遍,还是不行。之后和别人交流了一下,发现这个题居然在卡数据,还转卡1000000007等一系列有特殊原因的数,然后我把变成了
就可以了。后来我又试了试,发现111111和987也可以。(这怕不就是面向数据编程/狗头)
import java.util.*;public class Main{static int lll=987;static long testPosition(long l,long ll) {long b=ll;long r = 1, base = l;while (b!=0) {if ((b & 1)!=0) {r *= base;r%=lll;}base *= base;base%=lll;b >>= 1;}return r;}public static void main(String []args){Scanner kb=new Scanner(System.in);int n=kb.nextInt();while(n--!=0){long a=kb.nextLong()%lll;long b=kb.nextLong()%lll;long c=kb.nextLong()%lll;long d=kb.nextLong();long e=kb.nextLong();long f=kb.nextLong();long g=kb.nextLong();a=testPosition(a,d);b=testPosition(b,e);c=testPosition(c,f);a=(a+b+c)%lll;g=g%lll;if (a!=g) {System.out.println("No");}else {System.out.println("Yes");}}}}
H、施魔法
首先,根据题干的意思与尝试,我们索要选取的必然是经排序后而产生的连续区间。然后这又是个动态规划问题
其中, 表示用掉前
个元素的最小代价。
然后就是个码代码了。
#include <bits/stdc++.h>using namespace std;const int N = 3e5 + 7;int dp[N], pre, a[N], n, k;int main() {scanf("%d%d", &n, &k);for (int i = 1; i <= n; ++i) scanf("%d", a + i);sort(a + 1, a + 1 + n);pre = -a[1];for (int i = 1; i < k; ++i) dp[i] = 2e9;for (int i = k; i <= n; ++i) {dp[i] = pre + a[i];pre = min(pre, dp[i - k + 1] - a[i - k + 2]);}cout << dp[n];return 0;}
