首先,没有爆0!没有爆0!!没有爆0!!! 差点G了
E Math
首先这道题,没有看懂题目。
原来x2+y2|k(xy+1)的意思是前面可以整除后面???????? 我直接%&¥%*#%(开玩笑)
队友还说是或的意思,人麻了。不过好像公式写反了。自己看原题吧,懒得改了。
一开始在手算想要找规律,在进行了十分钟无用功之后忽然想到为啥不用计算机打表,哪怕是打前面的数值较小的表也可以。。
然后就对着若大的一些表看找规律。
大概就相当于
i=2的情况下(2,8)–>(8,30) -->(30,112) -->(112,418) 规律很清晰了有没有
8* 22-2 = 30
3022-8=112
112 22-30=418;
当然 还有i=3,4,5…106 ,为什么是 106呢 因为n最大取值为1018
数据值太大,肯定不能用下标存,直接存数值就好了! 再sort排一个序,搞一个二分查找什么的,完美。(但是我不会写,代码是队友写的,我只有思路 )
哦,对了 要开__int128 听说 1e18也不会爆。
#include <bits/stdc++.h>
#define inf 0x7fffffff
#define ll long long
//#define int unsigned long long
#define int __int128
#define re int
#define eps 1e-8
#define ls(p) p<<1
#define rs(p) p<<1|1
#define pi acos(-1.0)
#define pb push_back
#define mk make_pair
#define P pair < int , int >
using namespace std;
const int N=5e6+5;
int a[N];
inline int read()
{
int X=0,w=0; char ch=0;
while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
return w?-X:X;
}
inline void write(int x)
{
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}
void solve()
{
int t=0;
a[++t]=1;
for(int i=2;i<=2000001;i++)
{
int temp1=i*i*i;
int temp2=i;
int temp3=0;
while(1)
{
if(temp1>1e18||temp1<0) break;
a[++t]=temp1;
temp3=temp2;
temp2=temp1;
temp1=temp2*i*i-temp3;
}
}
sort(a+1,a+t+1);
int now;
now=read();
while(now--)
{
int y;
y=read();
int x=upper_bound(a+1,a+t+1,y)-a;
write(x-1);
puts("");
}
}
signed main()
{
int T=1;
// cin>>T;
for(int index=1;index<=T;index++)
{
solve();
// puts("");
}
return 0;
}
J题 Counting Triangles
好了 接下来是J题, 没想到有一天我还有机会看图论的题。
JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ
大概的意思呢就是说,给了你一个完全图,给了你每一条边的颜色,可能是黑色或者白色(具体记不清了,反正是两种),然后就要你求任意三条边连成的三角形是同色的还是异色的。(就是说三条边的颜色是不是一样嘛) 。
是不是很漂亮。
然后发现直接求是很难求解的,因为被卡了时间复杂度。我们需要在n2的时间复杂度内算出来。
最后是采用一个简单的容斥定理。直接求相同的不好求,那么我们求不同的。遍历每一个节点。那么异色的三角形的个数我们认为是这个节点的红色的边的数量乘以蓝色的边的数量加起来。
把每个节点的都加起来,最后是每个三角形都被计算了两次,然后又因为是完全图,我们很容易算出来所有边的个数的。减去就好了。
#include <bits/stdc++.h>
#define inf 0x7fffffff
#define ll long long
#define int long long
//#define double long double
//#define double long long
#define re int
//#define void inline void
#define eps 1e-8
//#define mod 1e9+7
#define ls(p) p<<1
#define rs(p) p<<1|1
#define pi acos(-1.0)
#define pb push_back
#define mk make_pair
#define P pair < int , int >
using namespace std;
const int mod=1e9+7;
//const int inf=1e18;
const int M=1e8;
const int N=8e3+5;//??????.???? 4e8
namespace GenHelper
{
unsigned z1,z2,z3,z4,b,u;
unsigned get()
{
b=((z1<<6)^z1)>>13;
z1=((z1&4294967294U)<<18)^b;
b=((z2<<2)^z2)>>27;
z2=((z2&4294967288U)<<2)^b;
b=((z3<<13)^z3)>>21;
z3=((z3&4294967280U)<<7)^b;
b=((z4<<3)^z4)>>12;
z4=((z4&4294967168U)<<13)^b;
return (z1^z2^z3^z4);
}
bool read() {
while (!u) u = get();
bool res = u & 1;
u >>= 1; return res;
}
void srand(int x)
{
z1=x;
z2=(~x)^0x233333333U;
z3=x^0x1234598766U;
z4=(~x)+51;
u = 0;
}
}
using namespace GenHelper;
bool edge[N][N];
int v[N];
int ans,cnt;
void solve()
{
int n, seed;
int ans=0;
cin>>n>>seed;
srand(seed);
for(re i=1;i<=n;i++) for(re j=i+1;j<=n;j++) edge[j][i]=edge[i][j]=read();
for(re i=1;i<=n;i++) for(re j=i+1;j<=n;j++) if(edge[i][j]) v[i]++,v[j]++;
for(re i=1;i<=n;i++) cnt+=v[i]*(n-1-v[i]);
ans=(n-1)*(n-2)*n/6-cnt/2;
cout<<ans<<endl;
}
signed main()
{
int T=1;
// cin>>T;
for(int index=1;index<=T;index++)
{
solve();
// puts("");
}
return 0;
}
/*
*/
B题 Black and white
本来我想着是只要一条线连着左上角到右下角或者相反就可以补全整个矩形。后来发现存在着一些的问题。如果我是角落的地方都填MAX那不是BUG了么?
后来又想着先找到最小的2*2的方框,然后根据周围的最小值向外扩充。
最后看了题解,二分图。没听说过,就是点亮一个方框(i,j)就相当于链接了第i行和第j列
我们最后也就是要连接出来一个二分图,是连通的二分图。我们优先选择权值比较小,且没有在一个集合中的两个点进行链接。这样,这不是最小生成树么?
用并查集就可以解决了。
这里注意下find函数,要在寻找的过程中进行修改值,这样可以减小很大的时间复杂度不至于超时。
另外P mk pb 宏定义真的很方便 还有auto 开优化真的香 可惜dev不支持编译
#include <bits/stdc++.h>
#define inf 0x7fffffff
#define ll long long
#define int long long
//#define double long double
//#define double long long
#define re int
//#define void inline void
#define eps 1e-8
//#define mod 1e9+7
#define ls(p) p<<1
#define rs(p) p<<1|1
#define pi acos(-1.0)
#define pb push_back
#define mk make_pair
#define P pair < int , int >
using namespace std;
const int mod=1e9+7;
//const int inf=1e18;
const int M=1e8;
const int N=8e3+5;//??????.???? 4e8
int F[100005]={0};
int a[100005]={0};
vector<P>v[100005];
int fd(int f)
{
return f==F[f]?f:(F[f]=fd(F[f]));
}
void solve()
{
int n,m,a,b,c,d,p;
cin>>n>>m>>a>>b>>c>>d>>p;
for(re i=1;i<=n+m;i++)F[i]=i;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
a=(a*a*b+a*c+d)%p;
v[a].pb(mk(i,j+n));
}
}
int ans=0;
for(int i=0;i<p;i++)
{
for(auto u:v[i])
{
int x=fd(u.first);
int y=fd(u.second);
if(x!=y)
{
ans+=i;
F[x]=y;
}
}
}
cout<<ans<<endl;
}
signed main()
{
int T=1;
// cin>>T;
for(int index=1;index<=T;index++)
{
solve();
// puts("");
}
return 0;
}
/*
*/