A-符合条件的整数
题意:
给定两个整数N,M,表示区间 [, ) ,请求出在这个区间里有多少个整数i满足i % 7=1
题解:两种方法一种推公式,另一种暴力枚举
推公式:
我们细心列出一部分就会发现
0 1 2 3 4 5 6 1 1 1 2 3 5 10
后一个是前一个的2倍-1 如果这个指数能整除3那么那是前一个的二倍,就不用减一,其实就是因为他本身是%7=1,所以把他本身加上。知道这个都简单多了
暴力枚举:
找到左端点第一个%7=1,然后+7循环就好。
公式代码:
#include <map> #include <queue> #include <string> #include<iostream> #include<stdio.h> #include<string.h> #include <algorithm> #include <math.h> typedef long long ll; typedef unsigned long long ull; using namespace std; typedef pair<ll,ll> pii; #define mem(a,x) memset(a,x,sizeof(a)) #define debug(x) cout << #x << ": " << x << endl; #define rep(i,n) for(int i=0;i<(n);++i) #define repi(i,a,b) for(int i=int(a);i<=(b);++i) #define repr(i,b,a) for(int i=int(b);i>=(a);--i) const int maxn=2e5+1010; #define inf 0x3f3f3f3f #define sf scanf #define pf printf const int mod=998244353; const int MOD=10007; inline int read() { int x=0; bool t=false; char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')t=true,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return t?-x:x; } /*priority_queue<ll , vector<ll> , greater<ll> > mn;//上 小根堆 小到大 priority_queue<ll , vector<ll> , less<ll> > mx;//下 大根堆 大到小 map<ll,ll>mp;*/ ll n,m,t,l,r,p; ll sum,ans,res,cnt,flag,maxx,minn; bool isprime[maxn]; ll a[maxn],b[maxn],c[maxn]; ll dis[maxn],vis[maxn]; ll dp[1010][1010]; string str,s; #define read read() int main(){ cin>>n>>m; a[0]=1; a[1]=1; a[2]=1; for(int i=3;i<=m;i++) { a[i]=a[i-1]*2-1; if(i%3==0) a[i]++; } sum=a[m]-a[n]; if(n%3==0) sum++; if(m%3==0) sum--; cout<<sum<<endl; return 0; }
暴力枚举代码:
#include <map> #include <queue> #include <string> #include<iostream> #include<stdio.h> #include<string.h> #include <algorithm> #include <math.h> typedef long long ll; typedef unsigned long long ull; using namespace std; typedef pair<ll,ll> pii; #define mem(a,x) memset(a,x,sizeof(a)) #define debug(x) cout << #x << ": " << x << endl; #define rep(i,n) for(int i=0;i<(n);++i) #define repi(i,a,b) for(int i=int(a);i<=(b);++i) #define repr(i,b,a) for(int i=int(b);i>=(a);--i) const int maxn=2e5+1010; #define inf 0x3f3f3f3f #define sf scanf #define pf printf const int mod=998244353; const int MOD=10007; inline int read() { int x=0; bool t=false; char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')t=true,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return t?-x:x; } /*priority_queue<ll , vector<ll> , greater<ll> > mn;//上 小根堆 小到大 priority_queue<ll , vector<ll> , less<ll> > mx;//下 大根堆 大到小 map<ll,ll>mp;*/ ll n,m,t,l,r,p; ll sum,ans,res,cnt,flag,maxx,minn; bool isprime[maxn]; ll a[maxn],b[maxn],c[maxn]; ll dis[maxn],vis[maxn]; ll dp[1010][1010]; string str,s; #define read read() int main(){ cin>>n>>m; a[0]=1; for(int i=1;i<=66;i++) a[i]=a[i-1]*2; l=a[n]; while(l%7!=1) l++; for(ll i=l;i<a[m];i+=7) sum++; cout<<sum<<endl; return 0; }
B-Relic DISCOVERY
题意:就相当如:给你几个商品,给出你单价和数量,让你求出总钱数
题解:听完题意就能直接出来了,就是单价x数量和。
代码:
#include <map> #include <queue> #include <string> #include<iostream> #include<stdio.h> #include<string.h> #include <algorithm> #include <math.h> typedef long long ll; typedef unsigned long long ull; using namespace std; typedef pair<ll,ll> pii; #define mem(a,x) memset(a,x,sizeof(a)) #define debug(x) cout << #x << ": " << x << endl; #define rep(i,n) for(int i=0;i<(n);++i) #define repi(i,a,b) for(int i=int(a);i<=(b);++i) #define repr(i,b,a) for(int i=int(b);i>=(a);--i) const int maxn=2e5+1010; #define inf 0x3f3f3f3f #define sf scanf #define pf printf const int mod=998244353; const int MOD=10007; inline int read() { int x=0; bool t=false; char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')t=true,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return t?-x:x; } /*priority_queue<ll , vector<ll> , greater<ll> > mn;//上 小根堆 小到大 priority_queue<ll , vector<ll> , less<ll> > mx;//下 大根堆 大到小 map<ll,ll>mp;*/ ll n,m,t,l,r,p; ll sum,ans,res,cnt,flag,maxx,minn; bool isprime[maxn]; ll a[maxn],b[maxn],c[maxn]; ll dis[maxn],vis[maxn]; ll dp[1010][1010]; string str,s; #define read read() int main(){ t=read; while(t--){ n=read; sum=0; for(int i=1;i<=n;i++) { a[i]=read,b[i]=read; sum+=a[i]*b[i]; } cout<<sum<<endl; } return 0; }
D-石子游戏
题意:
Alice和Bob在玩游戏,他们面前有n堆石子,对于这些石子他们可以轮流进行一些操作,不能进行下去的人则输掉这局游戏。
可以进行两种操作:
- 把石子数为奇数的一堆石子分为两堆正整数个石子
- 把两堆石子数为偶数的石子合并为一堆
两人都足够聪明,会按照最优策略操作。现在Alice想知道自己先手,谁能最后赢得比赛。
题解:
分析一下:两种操作:
1,奇数分解:一个大于1的奇数(x)可以分解成1个奇数1个偶数,那么我们往极端上想,如果分成1和(x-1)(偶数) (x-1)偶数可以跟另一偶数(数列中的一个或者其他奇数生成的)合成偶数 最后经过两步就是把 原奇数 转出来个1并把剩下的加到另一偶数上 所以奇数不用管。一定是经过偶数次,对结果相当于没代价。
2,偶数合成:两个偶数合成一个奇数,合成这个偶数,所以最后结果就是交少了一个偶数
最后会化成 一个偶数 和若干个1。
代码:
#include <map> #include <queue> #include <string> #include<iostream> #include<stdio.h> #include<string.h> #include <algorithm> #include <math.h> typedef long long ll; typedef unsigned long long ull; using namespace std; typedef pair<ll,ll> pii; #define mem(a,x) memset(a,x,sizeof(a)) #define debug(x) cout << #x << ": " << x << endl; #define rep(i,n) for(int i=0;i<(n);++i) #define repi(i,a,b) for(int i=int(a);i<=(b);++i) #define repr(i,b,a) for(int i=int(b);i>=(a);--i) const int maxn=2e5+1010; #define inf 0x3f3f3f3f #define sf scanf #define pf printf const int mod=998244353; const int MOD=10007; inline int read() { int x=0; bool t=false; char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')t=true,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return t?-x:x; } /*priority_queue<ll , vector<ll> , greater<ll> > mn;//上 小根堆 小到大 priority_queue<ll , vector<ll> , less<ll> > mx;//下 大根堆 大到小 map<ll,ll>mp;*/ ll n,m,t,l,r,p; ll sum,ans,res,cnt,flag,maxx,minn; bool isprime[maxn]; ll a[maxn],b[maxn],c[maxn]; ll dis[maxn],vis[maxn]; ll dp[1010][1010]; string str,s; #define read read() int main(){ n=read; for(int i=1;i<=n;i++){ a[i]=read; if(a[i]%2==0) sum++;//偶数 //奇数分解成1和另一偶数 偶数可以跟另一偶数合成偶数 最后经过两步就是把 原奇数 转出来个1并把剩下的加到另一偶数上 所以奇数不用管 } flag=1; while(sum>1){ sum--;//每次两个偶数相加生成一个偶数 最后结果就是减少一个偶数 flag=-flag; } if(flag==-1) cout<<"Alice"<<endl; else cout<<"Bob"<<endl; return 0; }
E-凸多边形的划分
题意:
给定一个具有N个顶点的凸多边形,将顶点从1至N标号,每个顶点的权值都是一个正整数。将这个凸多边形划分成N-2个互不相交的三角形,试求这些三角形顶点的权值乘积和至少为多少。
题解:知识点高精度+区间DP
这个题用到区间DP这个应该很好想到
找[i,j]最优值就是找一点k使得[左一半+右一半+a[i]a[j]a[k]]最小这样[i,j]就是最优解
所以我们的状态转移方程是:
dp[i,j]=min(dp[i,j],dp[i,k]+dp[k,j]+a[i]*a[k]*a[j]);
但鉴于这个题的数据量我们不得不用上高精度
代码:
#include <map> #include <queue> #include <string> #include<iostream> #include<stdio.h> #include<string.h> #include <algorithm> #include <math.h> typedef long long ll; #define pll __int128 typedef unsigned long long ull; using namespace std; typedef pair<ll,ll> pii; #define mem(a,x) memset(a,x,sizeof(a)) #define debug(x) cout << #x << ": " << x << endl; #define rep(i,n) for(int i=0;i<(n);++i) #define repi(i,a,b) for(int i=int(a);i<=(b);++i) #define repr(i,b,a) for(int i=int(b);i>=(a);--i) const int maxn=2e5+1010; #define inf 0x3f3f3f3f #define sf scanf #define pf printf const int mod=998244353; const int MOD=10007; inline int read() { int x=0; bool t=false; char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')t=true,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return t?-x:x; } /*priority_queue<ll , vector<ll> , greater<ll> > mn;//上 小根堆 小到大 priority_queue<ll , vector<ll> , less<ll> > mx;//下 大根堆 大到小 map<ll,ll>mp;*/ ll n,m,t,l,r,p; ll sum,ans,res,cnt,flag,maxx,minn; bool isprime[maxn]; ll b[maxn],c[maxn]; ll dis[maxn],vis[maxn]; string str,s; pll dp[55][55]; pll a[55]; void print(pll x) { if (!x) return ; if (x < 0) putchar('-'), x = -x; print(x / 10); putchar(x % 10 + '0'); } #define read read() int main(){ sf("%lld",&n); for(int i=1;i<=n;i++){ int x; x=read; a[i]=x; } memset(dp, 0, sizeof(dp)); for(int len=2;len<=n;len++){//长度 for(int i=1;i+len<=n;i++)//起点 { int j=i+len;//终点 dp[i][j]=1e30+10; for(int k=i+1;k<j;k++)//找到内部最优解 dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]+a[i]*a[j]*a[k]); } } if(dp[1][n]==0) cout<<"0"<<endl; else print(dp[1][n]); return 0; }