cf 603 数论 n/(n/i) 并查集 之后结果影响之前

https://codeforces.com/contest/1263
A
题意
a b c >0两两-1,求最多减多少次
设 a<b<c 如果a+b>=c 则总可以化成 a+b=c||c+1,答案就是(a+b+c)/2
如果 a+b<c 则答案就是a+b

#include <stdio.h>
#include <algorithm>
using namespace std;
int a[5];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        for(int i=1;i<=3;i++)
            scanf("%d",&a[i]);
        sort(a+1,a+4);
        if(a[1]+a[2]>=a[3])
            printf("%d\n",(a[1]+a[2]+a[3])/2);
        else 
            printf("%d\n",a[1]+a[2]);
    }
}

B
https://codeforces.com/contest/1263/problem/B
题意输入10个4为数的0~9的密码,要求把相等的密码修改成不相等
因为只有10个密码,所以我们只需修改其中一位0~9遍历

#include <stdio.h>
#include <iostream>
#include <map>
#include <string>
using namespace std;
string s[19];            //用来存密码
map<string,int>mp;       //查看哪些密码出现过
void change(string &s)     //全局变量 
{
    for(char i='0';i<='9';i++)
    {
        s[0]=i;
        if(!mp[s])            //没出现过这个数字
        {
            mp[s]=1;
            break;
        }
    }
}
int main()
{
    int t,n;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            cin>>s[i];
        mp.clear();
        int ans=0;
        for(int i=1;i<=n;i++)mp[s[i]]++;
        for(int i=1;i<=n;i++)
        {
            if(mp[s[i]]>1)
            {
                mp[s[i]]--;
                change(s[i]);
                ans++;
            }
        }
        printf("%d\n",ans);
        for(int i=1;i<=n;i++)
            std::cout << s[i] << std::endl;
    }
}

C
https://codeforces.com/contest/1263/problem/C

if n=5, then the answer is equal to the sequence 0,1,2,5. Each of the
sequence values (and only them) can be obtained as ⌊n/k⌋ for some
positive integer k (where ⌊x⌋ is the value of x rounded down):
0=⌊5/7⌋, 1=⌊5/5⌋, 2=⌊5/2⌋, 5=⌊5/1⌋.

暴力做法是遍历每一个1~n+1 然后求出n/(i)不相等的答案
但我们会发现如n=100 i=26 27 28 ……33 n/i 都是等于3
有个技巧 i=n/(n/i)可以跳到
n/i(原)=n/i(新)的最远位置
即从26 跳到33
因为当n/i=k n%i==0 则i不变
n%i!=0 则n/k就等于最大的n/i=k

#include <stdio.h>
int ans[10000000];
int main()
{
	int t,n;
	int cnt;
	scanf("%d",&t);
	while(t--)
	{
		cnt=0;
		scanf("%d",&n);
		for(int i=1;i<=n;i++)ans[++cnt]=n/i,i=n/(n/i);
		printf("%d\n0",cnt+1);
		for(int i=cnt;i;i--)
			printf(" %d",ans[i]);
		puts(" "); 
	}
}

https://codeforces.com/contest/1263/problem/D
题意
two passwords a and b are equivalent if there is a letter, that exists in both a and b;
two passwords a and b are equivalent if there is a password c from the list, which is equivalent to both a and b.
即如果 有一个字母和别人相等 这两个属于同一个集合abcd……xyz包括所有集合

/*
这题难点就是如何将a b ab他们属于同一个集合 ,且计数为1,即后面加入的
字符串会影响之前的集合
*/ 
#include <stdio.h>
int fa[28],a[28],n,cnt;
char s[55];
int find(int x)
{
    return x==fa[x]?x:fa[x]=find(fa[x]);
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=26;i++)fa[i]=i;
    while(n--)
    {
        scanf("%s",s);
        for(int i=0;s[i];i++)a[s[i]-'a'+1]=1;   //出现字母,即不合并有多少集合 
        for(int i=1;s[i];i++)                   //cnt =合并的次数
        {
            int p=find(s[i]-'a'+1),q=find(s[i-1]-'a'+1);
            if(p!=q)fa[p]=q,cnt++;      //出现新的字母,并放入同一个集合 
        }                               //某个字符串如果与之前的都不交叉,则 
    }                                   //独立出来 
	for(int i=1;i<=26;i++)cnt-=a[i];    //独立出来的个数 =不合并-合并的次数 
        printf("%d",-cnt);
}
发布了88 篇原创文章 · 获赞 8 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_44879687/article/details/103322799