AtCoder Beginner Contest 246
题意:要买n个商品,第 i i i个商品价格为 a i a_i ai,同时有k张优惠券,每张优惠券可以减免x元。
问要买下这n个商品最少要多少钱。
贪心,优先把大于x的商品用优惠券,若还有剩余,则优先把价格大的用优惠券减免。
code:
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define ios std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define int long long
#define x first
#define y second
typedef pair<int,int> pii;
//head
const int N=2e5+10,mod=998244353;
int a[N];
int n,k,x;
void work()
{
cin>>n>>k>>x;
int sum=0;
for(int i=1;i<=n;i++){
cin>>a[i];
sum+=a[i]/x;
a[i]%=x;
}
int ans=0;
if(sum>=k){
ans+=(sum-k)*x;
for(int i=1;i<=n;i++) ans+=a[i];
}
else {
sort(a+1,a+1+n);
k-=sum;
for(int i=1;i<=n;i++) ans+=a[i];
for(int i=n;i>=1;i--){
if(!k) break;
ans-=a[i];
k--;
}
}
cout<<ans<<endl;
}
signed main()
{
int t;
t=1;
while(t--) work();
return 0;
}
题意:给定N,求出最小的X,满足下列条件:
- X ≥ N X \geq N X≥N
- 存在一对非负整数 a , b , 满足: X = a 3 + a 2 b + a b 2 + b 3 存在一对非负整数a,b,满足:X=a^3+a^2b+ab^2+b^3 存在一对非负整数a,b,满足:X=a3+a2b+ab2+b3
0 ≤ N ≤ 10 18 0 \leq N \leq {10}^{18} 0≤N≤1018.
注意到N的数据范围为 10 18 {10}^{18} 1018,因此a或b的范围为 1 0 6 10^6 106 , 因此我们可以枚举a,然后二分找到满足条件的最小的b, 然后不断更新答案即可。
code:
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define ios std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define int long long
#define x first
#define y second
typedef pair<int,int> pii;
//head
const int N=2e5+10,mod=998244353;
int f(int a,int b)
{
return a*a*a+a*a*b+a*b*b+b*b*b;
}
void work()
{
int n;
cin>>n;
int ans=2e18;
for(int i=0;i<=1e6;i++){
int l=0,r=1e6;
while(l<r)
{
int mid=l+r>>1;
if(f(i,mid)>=n) r=mid;
else l=mid+1;
}
ans=min(ans,f(i,r));
}
cout<<ans<<endl;
}
signed main()
{
int t;
t=1;
while(t--) work();
return 0;
}
题意:给定 N ∗ N N*N N∗N的网格,给出起点和终点坐标,同时给出障碍物的坐标,问从起点到终点最少要走几步。
走的规则为:只能沿对角线斜着走,若斜着的路径上没有障碍物,则可以一步到达。
官方题解是01BFS,判断当前的方向,若当前的方向跟要上一步的方向一致,则边权为0,若不一致,则边权为1。用双端队列来实现即可。
还有一种做法是,把某个方向的点,能加入队列都加入队列,然后跟普通的bfs一样,正常的做,唯一不同的是对于每个点来说,如果当前方向已经被扩展过,就不需要再把它入队,因此st数组要多开一维来记录方向。如果不这样的话,会有很多点被扩展进队列里导致超时。(个人感觉官方的题解更对一些,这个做法不是很好想到)
第二种方法code:
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define ios std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//#define int long long
#define x first
#define y second
typedef pair<int,int> pii;
//head
const int N=2e3+10,mod=998244353;
char s[N][N];
int n;
bool st[N][N][4];
int sx,sy,ex,ey;
int dx[]={-1,1,1,-1},dy[]={1,1,-1,-1};
struct node{
int x,y,w;
};
bool check(int a,int b,int i)
{
if(a>n||b>n||a<1||b<1||s[a][b]=='#'||st[a][b][i]) return 0;
return 1;
}
int bfs()
{
queue<node> q;
q.push({sx,sy,0});
while(q.size())
{
auto t=q.front(); q.pop();
int x=t.x,y=t.y,w=t.w;
for(int i=0;i<4;i++){
int a=x+dx[i],b=y+dy[i];
while(check(a,b,i)) {
q.push({a,b,w+1});
st[a][b][i]=1;
if(a==ex&&b==ey) return w+1;
a+=dx[i]; b+=dy[i];
}
}
}
return -1;
}
void work()
{
cin>>n;
cin>>sx>>sy>>ex>>ey;
for(int i=1;i<=n;i++) cin>>s[i]+1;
int ans=bfs();
cout<<ans<<endl;
}
signed main()
{
int t;
t=1;
while(t--) work();
return 0;
}
题意:给定N个字符串,每个字符串都是字符串 a b c d e f g h i j k l m n o p q r s t u v w x y z abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz的子序列,同时给定L,求出每次只用某一个字符串,每个字符可以用多次,可以形成多少种长度为L的字符串。
1 ≤ N ≤ 18 1\leq N \leq 18 1≤N≤18, 1 ≤ L ≤ 1 0 9 1 \leq L \leq 10^9 1≤L≤109.
首先考虑如何计算答案,对于某个字符串,它对答案的贡献为: 长度 L {长度}^L 长度L,然后把每个字符串的答案相加即可。但是如果我们这样计算会发现一个问题,某些字符串会含有相同的字符,因此会有答案被重复计算。
因此我们要求的是各个字符串的并集,根据容斥原理,我们只需根据公式看哪些答案需要减去,哪些答案加上即可。(也就是偶数个事件的交集要减去,奇数个事件的交集要加上)。
对于交集,也就是求它们的公共字符有几个。
code:
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define ios std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define int long long
#define x first
#define y second
typedef pair<int,int> pii;
//head
const int N=20,mod=998244353;
string s[N];
int qmi(int a,int k)
{
int ans=1;
while(k)
{
if(k&1) ans=ans*a%mod;
a=a*a%mod;
k>>=1;
}
return ans;
}
void work()
{
int n,l;
cin>>n>>l;
for(int i=0;i<n;i++){
cin>>s[i];
}
int ans=0;
for(int i=0;i<(1<<n);i++){
int cnt=__builtin_popcount(i);
map<char,int> mp;
int sum=0;
for(int j=0;j<n;j++){
if((i>>j)&1){
for(auto ch:s[j]){
mp[ch]++;
if(mp[ch]==cnt) sum++;
}
}
}
if(cnt&1){//根据容斥原理,加上贡献
ans=(ans+qmi(sum,l))%mod;
}
else {//减去贡献
ans=(ans-qmi(sum,l)+mod)%mod;
}
}
cout<<ans<<endl;
}
signed main()
{
//ios;
int t;
t=1;
//cin>>t;
while(t--) work();
return 0;
}