CodeForces - 1213C
给出n,m,求小于等于 m 的范围内所有 n 的倍数的最后一位的和
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
int a[11];
int main()
{
int t;
cin>>t;
while(t--)
{
long long n,m,x;
cin>>n>>m;
x=m;
x=x%10;
long long s=0,k=m;
for(int i=1;i<=10;i++)
{
k=k%10;
a[i]=k;
s+=k;
k+=x;
}
long long z=n/m;
long long ans=0;
ans+=((z/10)*s);
z=z%10;
for(int i=1;i<=z;i++)
ans+=a[i];
cout<<ans<<endl;
}
return 0;
}
倍数的最后一位十个一循环
CodeForces - 1217B
x 个头, n 种砍法,第 i 种砍掉 di 个,长出 hi 个,每次任意使用某种砍法,问最少砍几次可以砍死
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
int t;
cin >> t;
while(t--){
int n, m, k, h, maxk = 0, maxd = -999999999;
cin >> n >> m;
for(int i = 1; i <= n; i++){
cin >> k >> h;
if(k > maxk){
maxk = k;
}
if(k - h > maxd){
maxd = k - h;
}
}
int ans = 1;
m = m - maxk;
if(m > 0){
if(maxd <= 0){
ans = -1;
}
else{
ans = ans + (m + maxd - 1) / maxd;
}
}
cout << ans << endl;
}
return 0;
}
思路也一样,但不知道为什么自己一写就runtime error了
CodeForces - 1217C
给一个字符串只有0和1,问你有多少个子串满足长度等于该子串的二进数值
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
int dis=18;
char s[maxn];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%s",s);
int sum=0;
int len=strlen(s);
int pre=0;
for(int i=0; i<len; i++)
{
if(s[i]=='0')
pre++;
else
{
int r=i;
int cnt=1;
for(int j=0; j<dis; j++)
{
if(cnt<=pre+(r-i+1))
sum++;
if(r==len-1)
break;
r++;
cnt=cnt*2+(s[r]-'0');
}
pre=0;
}
}
printf("%d\n",sum);
}
return 0;
}
二进制里面的所有的左移一位,相当于乘2,思路是选中一个位置,已经该位置前面有几个连续的0,然后再向后计算
CodeForces - 1213D1
给出 n 个数,一次操作是数组中的某个元素除以2下取整。问最少操作多少次可以使这个数组中有 k 个相等的数字。
#include<bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
const int maxx=2e5+100;
int cnt[maxx];
int num[maxx];
int a[maxx];
int n,k;
int main()
{
scanf("%d%d",&n,&k);
memset(cnt,0,sizeof(cnt));
memset(num,0,sizeof(num));
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
num[a[i]]++;
}
sort(a+1,a+1+n);
int ans=inf;
for(int i=1;i<=n;i++)
{
int x=a[i];
int cnt1=0;
while(x)
{
if(num[x]>=k) ans=min(ans,cnt[x]);
x>>=1;
cnt1++;
num[x]++;
cnt[x]+=cnt1;
}
}
cout<<ans<<endl;
}
这道题有很多细节需要注意:num[x]>=k 不能写 == ,因为可能有答案为0即不需要操作的情况,我没有做出了是没想到用cnt[x]记录到达现在的x数量需要操作的次数,不断的更新最小值。while(x)这一步也不能写成while(x>=a[1])因为也有情况需要把所有的数都除为0
CodeForces - 1217D
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=5010;
const int N=1e3+7;
const int inf=0x3f3f3f3f;
int head[maxn];
int nxt[maxn];
int to[maxn];
int vis[maxn];
int cnt;
int ans[maxn];
bool cyc;
void add(int u,int v){
cnt++;
to[cnt]=v;
nxt[cnt]=head[u];
head[u]=cnt;
}
void dfs(int u){
vis[u]=1;//点u已经被访问了但其子孙后代还没被访问完。
for(int i=head[u];i;i=nxt[i]){
int v=to[i];
if(vis[v]==0){//这是条树边
dfs(v);
ans[i]=1;
}
else if(vis[v]==2)//横断边
ans[i]=1;
else if(vis[v]==1)//返祖边
cyc=1,ans[i]=2;
}
vis[u]=2;//点u已经被访问了
}
int main(){
int n,m;scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
int u,v;scanf("%d%d",&u,&v);
add(u,v);
}
for(int i=1;i<=n;i++){
if(!vis[i])
dfs(i);
}
if(cyc)printf("2\n");
else printf("1\n");
for(int i=1;i<m;i++)printf("%d ",ans[i]);
printf("%d\n",ans[m]);
return 0;
}
题解
我还没怎么看明白。。