Problem - D - Codeforces 求因子判断x/i要放if里面!!!
问有几种方案可以使得x可以被表示为x因子的乘积,并且这些因子要是漂亮数,因子可以重复使用,那就想到了完全背包了,先求出x的因子,然后用map或者是两个数组存一下值,两个数组的话大于1e5就放在gid这个数组里,小于等于就放在id这个数组里,转移的时候就靠下标转移,因为数太大了,把数当成容量的话数组放不下,还有一些详情注释有;
D. Madoka and the Best School in Russia (dp?)_Bzdhxs_nt的博客-CSDN博客
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int t,x,d,dp[100005],id[100005],gid[100005];
int maxx=1e5+10;
vector<int>v;
int main(){
scanf("%d",&t);
while(t--){
v.clear();
scanf("%d%d",&x,&d);
for(int i=1;i*i<=x;i++){
if(x%i==0){
v.push_back(i);
if(i!=x/i) v.push_back(x/i);//这句话一定要放在括号里面!!!
}
}
sort(v.begin(),v.end());
for(int i=0;i<v.size();i++){
if(v[i]<=maxx) id[v[i]]=i;
else gid[x/v[i]]=i;
}
for(int i=0;i<=v.size();i++) dp[i]=0;
dp[0]=1;
for(int i=0;i<v.size();i++){
if(v[i]%d==0&&(v[i]/d)%d!=0){//只有是漂亮数才能进入循环
//cout<<v[i]<<" "<<i<<endl;
for(int j=0;j<v.size();j++){
if((x/v[i])%v[j]==0){//保证v[i]*v[j]也是x的因子
int u=v[i]*v[j],w=v[j];
int y=u>maxx?gid[x/u]:id[u];
int z=v[j]>maxx?gid[x/v[j]]:id[v[j]];
dp[y]+=dp[z];//用w来转移v[i]*v[j],从而也保证不会有错误的情况转移过去
// cout<<dp[mp[u]]<<" s "<<w<<" "<<v[i]<<endl;
}
}
}
}
if(dp[v.size()-1]>=2) printf("YES\n");
else printf("NO\n");
}
return 0;
}
Problem - C - Codeforces
这个题一开始想成了dp,但其实贪心就可以解决,每次攻占了一座城市就比较一下不更换的情况下攻占后面的城市所需要的花费和更换的情况下所需要的花费,如果后者更小就换城市;
Codeforces Round #782 (Div. 2) C. Line Empire - 知乎 (zhihu.com)
#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<cstdio>
#include<iomanip>
#include<map>
#include<cmath>
#include<vector>
#include<queue>
#include<deque>
#include<list>
#include<stack>
#include<set>
#include<ctime>
//HDU专用火车头
//#include <bits/stdc++.h>
#define ll long long
#define lowbit(x) ((-x)&(x))
using namespace std;
const int mod=1000000007;
const ll inf=1e18;
const ll bou=1e15;
const int maxn=1e7+5;
ll qpow(ll a,ll b){
ll res=1;
while(b){
if(b&1) res*=a;
a*=a;
b>>=1;
}
return res;
}
ll t,n,a,b,c[200005],sum[200005];
int main(){
//freopen("in.txt","r",stdin);
scanf("%lld",&t);
while(t--){
scanf("%lld%lld%lld",&n,&a,&b);
for(int i=1;i<=n;i++) scanf("%lld",&c[i]),sum[i]=sum[i-1]+c[i];
ll pos=0,ans=0;
for(int i=1;i<=n;i++){
ans+=b*(c[i]-pos);
if((sum[n]-sum[i]-(n-i)*pos)*b>=(sum[n]-sum[i]-(n-i)*c[i])*b+a*(c[i]-pos)){
ans+=a*(c[i]-pos);
pos=c[i];
}
}
printf("%lld\n",ans);
}
return 0;
}
Problem - B - Codeforces
只想到了对一个数操作偶数次其他的位置不会变,而没有想到对一个位置操作的次数与总的次数之差如果是偶数就不会变,是奇数就会改变,那问题就变得比较简单了,如果k是奇数那么如果想要最大都是要从1开始遍历,如果s[i]==‘1’那么在位置i上操作的次数必然是奇数才好,那就让他为1,多了也没什么用,如果为0就让他为偶数0,剩下的次数全放在ans[n]中,这样会是最优的情况,偶数也是一样的道理;
Codeforces Round #782 (Div. 2) A~D - 知乎 (zhihu.com)
#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<cstdio>
#include<iomanip>
#include<map>
#include<cmath>
#include<vector>
#include<queue>
#include<deque>
#include<list>
#include<stack>
#include<set>
#include<ctime>
//HDU专用火车头
//#include <bits/stdc++.h>
#define ll long long
#define lowbit(x) ((-x)&(x))
using namespace std;
const int mod=1000000007;
const ll inf=1e18;
const ll bou=1e15;
const int maxn=1e7+5;
ll qpow(ll a,ll b){
ll res=1;
while(b){
if(b&1) res*=a;
a*=a;
b>>=1;
}
return res;
}
ll t,n,k,ans[200005];
string s;
int main(){
//freopen("in.txt","r",stdin);
scanf("%lld",&t);
while(t--){
scanf("%lld%lld",&n,&k);
ll x=k;
cin>>s;s=" "+s;
for(int i=1;i<=n;i++) ans[i]=0;
if(k&1){
for(int i=1;i<=n;i++){
if(x<=0) break;
if(s[i]=='1'){
ans[i]=1,x--;
}
}
if(x>0) ans[n]+=x;
}
else{
for(int i=1;i<=n;i++){
if(x<=0) break;
if(s[i]=='0') ans[i]=1,x--;
}
if(x>0) ans[n]+=x;
}
for(int i=1;i<=n;i++){
if((k-ans[i])&1){
s[i]=s[i]=='1'?'0':'1';
}
cout<<s[i];
}
cout<<endl;
for(int i=1;i<=n;i++) cout<<ans[i]<<" ";
cout<<endl;
}
return 0;
}