并没有第四题。(还不会矩阵乘法加速线性数列)
题目1 : 数位翻转
时间限制:20000ms
单点时限:1000ms
内存限制:256MB
描述
给定一个数 n,你可以进行若干次操作,每次操作可以翻转 n 的二进制表示下的某一位,即将 0 变成 1,1 变成 0
现在小 Hi 想知道,至少需要多少次操作,才能将 n 变成 n-1
输入
一个正整数 n
1 ≤ n ≤ 109
输出
输出最少的操作次数
签到题,模拟一下取出各位二进制数即可,极水,怒A。
1 #include<cstdio> 2 #include<algorithm> 3 4 using namespace std; 5 6 int n,m,lena,lenb,ans; 7 int a[50],b[50]; 8 9 int main() 10 { 11 scanf("%d",&n); 12 m=n-1; 13 while(n) 14 { 15 a[++lena]=n%2; 16 n/=2; 17 } 18 while(m) 19 { 20 b[++lenb]=m%2; 21 m/=2; 22 } 23 int len=max(lena,lenb); 24 for(int i=1;i<=len;i++) 25 if(a[i]!=b[i]) ans++; 26 printf("%d",ans); 27 return 0; 28 }
题目2 : 最短公共子序列
时间限制:20000ms
单点时限:1000ms
内存限制:256MB
描述
给定一个 01 串 A,你需要找一个和它等长的01串 B,使得 A 和 B 的最长公共子序列最短
为了方便,你不需要输出 B,你只需要输出 A 和 B 的最长公共子序列的长度
输入
第一行一个 01 串 A
1 ≤ |A| ≤ 105
输出
输出最短的长度
- 样例输入
-
000111
- 样例输出
-
3
这个题啊,看起来有点唬人。一看到“最长公共子序列最短”,我上来就是一顿二分敲。后来发现check函数没法写,在固有的(我的)惯性思维中,把带字符串背景的都考虑成公共子串(中间不能有不同),而本题恰好反其道而行之,问子序列(子序列中间可间隔不同的)。
我们再冷静分析一下,状态要么是0,要么是1,手动模拟几组答案,可以发现答案正是A串中出现最少元素的个数。
抱着试试看的心态交了上去,竟然A了。qwq。 -
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 5 using namespace std; 6 7 char py[100090]; 8 int c,d,ans; 9 int a[100090],b[100090]; 10 11 int main() 12 { 13 scanf("%s",py+1); 14 int len=strlen(py+1); 15 for(int i=1;i<=len;i++) a[i]=(int)py[i]-'0'; 16 for(int i=1;i<=len;i++) 17 if(a[i]==1) c++;else d++; 18 ans=min(c,d); 19 printf("%d",ans); 20 return 0; 21 }
-
题目3 : 拼三角形
时间限制:20000ms单点时限:1000ms内存限制:256MB描述
给定 n 根木棍,第 i 根长度为 ai
现在你想用他们拼成尽量多的面积大于 0 的三角形,要求每根木棍只能被用一次,且不能折断
请你求出最多能拼出几个
输入
第一行一个正整数 n
第二行 n 个正整数 a1 … an
1 ≤ n ≤ 15
1 ≤ ai ≤ 109
输出
输出最多能拼出几个三角形
学长表示:一道暴搜题!巧了!我就不会写暴搜!qwq!
再和学长学习一下qwq。
由于最多有15根棒,所以顶多也就5个三角形。
然后我们就搜就行了qwq。我的模拟&贪心只能拿75分。
注释写在码里qwq。
#include<cstdio> #include<algorithm> using namespace std; typedef long long ll; int n; ll ans; int a[30]; bool flag[30]; void dfs(int cnt,int a1,int a2,int pre) {//cnt->当前已经选到第几个三角形 //a1->三角形中最短边,a2->三角形中最长边。 //pre->上一个选到哪了(下标) if(cnt==ans+1) { printf("%d",ans); exit(0);//void函数中想直接return 0结束程序用exit } if(!a1) { for(int i=pre+1;i<=n;i++) { if(flag[i]) continue; flag[i]=1; dfs(cnt,a[i],0,i); flag[i]=0; } } else if(a1>0&&a2<=0) { for(int i=pre+1;i<=n;i++) { if(flag[i]) continue; flag[i]=1; dfs(cnt,a1,a[i],i); flag[i]=0; } } else { for(int i=pre+1;i<=n;i++) { if(flag[i]) continue; if(a1+a2<=a[i]) return ; flag[i]=1; dfs(cnt+1,0,0,0); flag[i]=0; } } } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); sort(a+1,a+1+n); for(int i=n/3;i>=0;i--) { ans=i;//要几个 当前在哪 现在已经有几个边 dfs(1,0,0,0); } printf("%d",ans); return 0; }