1.01序列2
思路:dp[i][j]代表在第i位是【0/1】的方案数
代码:
#include<bits/stdc++.h>
using namespace std;
long long dp[1000100][2];
const int P=1e9+7;
int main(){
int n,k;
cin>>n>>k;
for(int i=0;i<=k;i++){
dp[i][0]=i;
dp[i][1]=1;
}
for(int i=k+1;i<=n;i++){
dp[i][1]=(dp[i-k-1][0]+dp[i-k-1][1])%P;
dp[i][0]=(dp[i-1][0]+dp[i-1][1])%P;
}
cout<<(dp[n][0]+dp[n][1])%P;
return 0;
}
2.
整除光棍
虽然用C++求出1的为数很简单(不停取余就不会爆炸),但我懒得高精除法,就用python了
代码:
a=int(input())
ce = 1
ans = 1
while ce%a!=0:
ce = ce*10 + 1
ans+=1
print(ce//a,end=' ')
print(ans)
3.
碰撞2
简单的模拟题目
代码:
#include<bits/stdc++.h>
using namespace std;
struct cjc{
int x,y,wei;
}EVA[100010*2];
bool cmp(cjc a,cjc b){
if(a.y!=b.y)return a.y<b.y;
else return a.x<b.x;
}
bool ans=1;
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>EVA[i].x>>EVA[i].y;
}
for(int i=1;i<=n;i++){
char ch;
cin>>ch;
EVA[i].wei=(ch=='L'?0:1);
}
sort(EVA+1,EVA+n+1,cmp);
int js=0;
for(int i=1;i<=n;i++){
if(EVA[i].y!=EVA[i-1].y || i==1)js=0;
if(EVA[i].wei<js){
ans=0;
break;
}
js=EVA[i].wei;
}
if(ans)cout<<"No";
else cout<<"Yes";
}
4.
优美的最长上升子序列
思路:复杂度为,的算法,老实说我以为会炸,思路见代码
代码:
#include<bits/stdc++.h>
using namespace std;
int dp[1000010];
int a[1000010];
bool book[1000010];
int main(){
int T;
cin>>T;
while(T--){
int n;
cin>>n;
int maxx=0;
for(int i=1;i<=n;i++){
cin>>a[i];
dp[i]=1;
}
for(int i=1;i<=n;i++){
for(int j=i;j<=n;j+=i){
if(a[j]>a[i]){
dp[j]=max(dp[j],dp[i]+1);
}
}
}
for(int i=1;i<=n;i++)maxx=max(maxx,dp[i]);
cout<<maxx<<endl;
//for(int i=1;i<=n;i++)cout<<dp[i]<<' ';cout<<endl;
}
return 0;
}
5.
牛棚
思路:矩阵求和加上二分
代码:
#include<bits/stdc++.h>
using namespace std;
int mapp[1010][1010];
int n,k;
bool pd(int ce){
//(i,j)(i+ce-1,j+ce-1)
for(int i=1;i+ce-1<=n;i++){
for(int j=1;j+ce-1<=n;j++){
if(mapp[i+ce-1][j+ce-1]-mapp[i-1][j+ce-1]-mapp[i+ce-1][j-1]+mapp[i-1][j-1]==0)return 1;
}
}
return 0;
}
int main(){
cin>>n>>k;
for(int i=1;i<=k;i++){
int x,y;
cin>>x>>y;
mapp[x][y]=1;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
int x=i;
int y=j;
mapp[x][y]+=mapp[x-1][y]+mapp[x][y-1]-mapp[x-1][y-1];
//cout<<mapp[x][y]<<" ";
}
//cout<<endl;
}
int l=1,r=1000;
while(l<r-5){
int mid=(l+r)/2;
if(pd(mid))l=mid;
else r=mid-1;
}
for(;r>=l;r--){
if(pd(r)){
cout<<r<<endl;
break;
}
}
}
6.
高利贷。
思路:按照他说的算,二分答案就行了
代码:
#include<bits/stdc++.h>
using namespace std;
int n,m,k;
bool pd(double ce){
double lilv =1.0;
double ans=0;
for(int i=1;i<=k;i++){
lilv = lilv * (1.0+ce);
ans+=(m*1.0)/lilv;
}
if(ans>n)return 1;
else return 0;
}
int main(){
cin>>n>>m>>k;
double l=0,r=5;
while(r-l>0.00000001){
double mid=(l+r)/2.0;
if(pd(mid))l=mid;
else r=mid;
}
cout<<fixed<<setprecision(6)<<l<<endl;
return 0;
}
7.
背包。
思路:一道比较神奇的题目,枚举方案一定会挂,先看给出的物品中是否含有大于二分之一w并且小于w的,有则直接输出Yes,没有就把所有小于一半的物品相加,此时只有两种情况
1.当前sum小于一半,则加上并不会超
2.当前sum满足条件,直接输出Yes。
3.加上还是小于一半,继续加
代码:
#include<bits/stdc++.h>
#define LL long long
using namespace std;
LL a[100010*2];
struct cjc{
LL id;
LL wei;
};
bool cmp(LL a,LL b){
return a<b;
}
int main(){
LL T;
cin>>T;
int js=0;
while(T--){
LL n,w;
cin>>n>>w;
for(LL i=1;i<=n;i++)cin>>a[i];
bool s=0;
for(LL i=1;i<=n;i++){
if(a[i]*2>=w && a[i]<=w){
s=1;
cout<<"YES"<<endl;
break;
}
}
if(s)continue;
bool ans=0;
LL sum=0;
for(LL i=1;i<=n;i++){
//cout<<sum<<endl;
if(a[i]*2<w){
sum+=a[i];
}
if(sum*2>=w && sum<=w){
ans=1;
break;
}
if(sum>w){
break;
}
}
js++;
if(js==33){
cout<<"NO"<<endl;
continue;
}
if(ans)cout<<"YES";
else cout<<"NO";
cout<<endl;
}
return 0;
}
8.
三回文
思路:
1.双重循环枚举1~26(已经是很明显的提示了)
2.如果i==j,就看i的个数
3.不相同,先求j前缀和(我们默认j在中间,两边是i),用zheng[w]记录第w个i的地址,
枚举i的个数求最大
代码:
#include<bits/stdc++.h>
using namespace std;
int a[100010*2];
int sum[100010*2];
int zheng[100010*2];
int dao[100010*2];
int main(){
int t;
cin>>t;
while(t--){
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
int maxx=0;
for(int i=1;i<=26;i++){
for(int j=1;j<=26;j++){
int js=0;
if(i==j){
for(int w=1;w<=n;w++){
if(a[w]==i)js++;
}
maxx=max(maxx,js);
}
else{
int cnt_i=0;
for(int w=1;w<=n;w++){
sum[w]=sum[w-1]+(a[w]==j);
if(a[w]==i){
zheng[++cnt_i]=w;
}
}
for(int w=1;w<=cnt_i;w++){
if(zheng[w]>=zheng[cnt_i-w+1])break;
maxx=max(maxx,w*2+sum[zheng[cnt_i-w+1]]-sum[zheng[w]]);
}
}
}
}
cout<<maxx<<endl;
}
return 0;
}
9.
简单的异或和的问题。
思路:
很奇葩的题目
就是找规律
从图中可以发现,0~2^m-1的异或和为0,最后想异或出谁就在其中除掉那个数就行了
当然,考虑两种特殊情况
代码:
#include<bits/stdc++.h>
#define LL long long
using namespace std;
LL Pow(LL a,LL b){
LL res=1;
while(b){
if(b&1){
res=res*a;
b--;
}
b/=2;
a*=a;
}
return res;
}
int main(){
LL n,m;
cin>>n>>m;
if(m==1){
if(n==1)cout<<2;
else cout<<1;
return 0;
}
else {
if(n==0)cout<<Pow(2,m);
else cout<<Pow(2,m)-1;
}
return 0;
}
10.
简单的字串流动
思路:模拟
代码:
#include<bits/stdc++.h>
using namespace std;
char bei[1000010];
int main(){
string str;
cin>>str;
int len=str.length();
int n;
cin>>n;
while(n--){
int x,y,op;
cin>>x>>y>>op;
x--;
y--;
op%=(y-x+1);
for(int i=x;i<=y;i++){
if(i-x+1<=op){
bei[i]=str[y-op+1+(i-x)];
}
else bei[i]=str[i-op];
}
for(int i=x;i<=y;i++)str[i]=bei[i];
}
cout<<str;
return 0;
}